aboutsummaryrefslogtreecommitdiffstats
path: root/src/world.cpp
blob: d05d5c181e99705cd57c2caf5016aa3ab5c82b53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <world.h>

#define getWidth(w) ((w->lineCount-GEN_INC)*HLINE)

#define GEN_INC 10
#define GRASS_HEIGHT 4

void safeSetColor(int r,int g,int b){
	if(r>255)r=255;
	if(g>255)g=255;
	if(b>255)b=255;
	if(r<0)r=0;
	if(g<0)g=0;
	if(b<0)b=0;
	glColor3ub(r,g,b);
}

World::World(unsigned int width){
	unsigned int i;
	float inc;
	lineCount=width+GEN_INC;
	line=(struct line_t *)calloc(lineCount,sizeof(struct line_t));	// allocate space for the array of lines
	line[0].y=80;
	for(i=GEN_INC;i<lineCount;i+=GEN_INC){
		line[i].y=rand()%8-4+line[i-GEN_INC].y;
		if(line[i].y<60)line[i].y=60;
		if(line[i].y>110)line[i].y=110;
	}
	for(i=0;i<lineCount-GEN_INC;i++){
		if(!i||!(i%GEN_INC)){
			inc=(line[i+GEN_INC].y-line[i].y)/(float)GEN_INC;
		}else{
			line[i].y=line[i-1].y+inc;
		}
		line[i].color=rand()%20+130;
	}
	x_start=0-getWidth(this)/2+GEN_INC/2*HLINE;
	behind=infront=NULL;
	toLeft=toRight=NULL;
}

World::~World(void){
	free(line);
}

void World::draw(vec2 *vec){
	static float yoff=50;
	static int shade=0;
	static World *root,*current;
	int i,ie,v_offset,cx_start;
	struct line_t *cline;
	root=current=this;
LOOP1:
	if(current->behind){
		yoff+=50;
		shade+=40;
		current=current->behind;
		goto LOOP1;
	}
LOOP2:
	v_offset=(vec->x-current->x_start)/HLINE;
	i=v_offset-SCREEN_WIDTH/(yoff/25);
	if(i<0)i=0;
	ie=v_offset+SCREEN_WIDTH/(yoff/25);
	if(ie>current->lineCount)ie=current->lineCount;
	//std::cout<<v_offset<<" "<<i<<" "<<ie<<yoff<<std::endl;
	cline=current->line;
	cx_start=current->x_start;
	glBegin(GL_QUADS);
		for(i=i;i<ie-GEN_INC;i++){
			cline[i].y+=(yoff-50);
			safeSetColor(shade,200+shade,shade);
			glVertex2i(cx_start+i*HLINE      ,cline[i].y);
			glVertex2i(cx_start+i*HLINE+HLINE,cline[i].y);
			glVertex2i(cx_start+i*HLINE+HLINE,cline[i].y-GRASS_HEIGHT);
			glVertex2i(cx_start+i*HLINE		,cline[i].y-GRASS_HEIGHT);
			safeSetColor(cline[i].color+shade,cline[i].color-50+shade,cline[i].color-100+shade);
			glVertex2i(cx_start+i*HLINE      ,cline[i].y-GRASS_HEIGHT);
			glVertex2i(cx_start+i*HLINE+HLINE,cline[i].y-GRASS_HEIGHT);
			glVertex2i(cx_start+i*HLINE+HLINE,0);
			glVertex2i(cx_start+i*HLINE		 ,0);
			cline[i].y-=(yoff-50);
		}
	glEnd();
	if(current->infront){
		yoff-=50;
		shade-=40;
		current=current->infront;
		goto LOOP2;
	}else{
		yoff=50;
		shade=40;
	}
}

void World::detect(vec2 *v,vec2 *vel,const float width){
	unsigned int i;
	// Vertical checks
	i=(v->x+width/2-x_start)/HLINE;
	if(v->y<=line[i].y){
		vel->y=0;
		v->y=line[i].y+HLINE/2;
	}else{
		vel->y-=.01;
	}
	// Horizontal checks
	if(v->x<x_start){
		vel->x=0;
		v->x=x_start+HLINE/2;
	}else if(v->x+width+HLINE>x_start+getWidth(this)){
		vel->x=0;
		v->x=x_start+getWidth(this)-width-HLINE;
	}
}

void World::addLayer(unsigned int width){
	if(behind){
		behind->addLayer(width);
		return;
	}
	behind=new World(width);
	behind->infront=this;
}

World *World::goWorldLeft(vec2 *loc,const float width){
	if(toLeft&&loc->x<x_start+HLINE*10){
		loc->x=toLeft->x_start+getWidth(toLeft)-HLINE*10;
		loc->y=toLeft->line[0].y;
		return toLeft;
	}
	return this;
}

World *World::goWorldRight(vec2 *loc,const float width){
	if(toRight&&loc->x+width>x_start+getWidth(this)-HLINE*10){
		loc->x=toRight->x_start+HLINE*10;
		loc->y=toRight->line[toRight->lineCount-GEN_INC-1].y;
		return toRight;
	}
	return this;
}

World *World::goWorldBack(vec2 *loc,const float width){
	if(behind&&loc->x>(int)(0-getWidth(behind)/2)&&loc->x<getWidth(behind)/2){
		return behind;
	}
	return this;
}

World *World::goWorldFront(vec2 *loc,const float width){
	if(infront&&loc->x>(int)(0-getWidth(infront)/2)&&loc->x<getWidth(infront)/2){
		return infront;
	}
	return this;
}