forked from CamGomezDev/SnakeDijkstraAI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSnake.pde
More file actions
161 lines (144 loc) · 4.51 KB
/
Snake.pde
File metadata and controls
161 lines (144 loc) · 4.51 KB
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
156
157
158
159
160
161
/*
En su mayor parte esta es una clase Snake estándar para
este juego. La única diferencia es el objeto controller
que es el que aplica la búsqueda
*/
class Snake {
int length = 0;
boolean justAte = false;
Controller controller = new Controller();
PVector[] pos = new PVector[1]; // arreglo de posiciones del cuerpo de la serpiente
PVector vel = new PVector(1,0);
PVector prev_head = new PVector(0,0);
/* La snake virtual es para cuando está haciendo la búsqueda,
que se crea una virtual que es la que hace el recorrido que comprueba
si el camino está libre */
Snake(boolean isVirtual) {
vel.mult(scl);
pos[0] = new PVector(floor(horSqrs/2)*scl,floor(verSqrs/2)*scl);
// renderizar solo si es virtual
if(!isVirtual) {
this.square(pos[0].x, pos[0].y);
}
}
/* Se ejecuta en cada fotograma, esta es toda la lógica principal del juego Snake */
void update() {
justAte = false;
prev_head = pos[0].get();
pos[0].add(vel);
this.checkEatFood();
this.checkBoundaries();
this.move();
this.checkCollBody();
}
// Se ejecuta en cada fotograma, esta es la búsqueda
void render() {
for(int i = 0; i < this.pos.length-1; i++) {
square(this.pos[i].x, this.pos[i].y);
/* Todo lo que sigue es para dibujar un rectangulito entre
dos cuadrados del cuerpo, esto es para que la serpiente
se vea continua y no como muchos cuadrados separados.
Se puede comentar todo el bloque para ver qué pasa. */
// Misma columna
if(pos[i].x == pos[i+1].x) {
// Arreglo aumenta hacia abajo
if(pos[i].y < pos[i+1].y) {
rect(pos[i].x + 2, pos[i].y + scl - 1, scl - 3, 3);
}
// Arreglo aumenta hacia arriba
if(pos[i].y > pos[i+1].y) {
rect(pos[i].x + 2, pos[i+1].y + scl - 1, scl - 3, 3);
}
}
// Misma fila
if(pos[i].y == pos[i+1].y) {
// Arreglo aumenta hacia la derecha
if(pos[i].x < pos[i+1].x) {
rect(pos[i].x + scl - 1, pos[i].y + 2, 3, scl - 3);
}
// Arreglo aumenta hacia la izquiera
if(pos[i].x > pos[i+1].x) {
rect(pos[i+1].x + scl - 1, pos[i].y + 2, 3, scl - 3);
}
}
}
square(pos[pos.length-1].x, pos[pos.length-1].y); // dibujar última parte del cuerpo
}
// Aquí se mueve el cuerpo de la serpiente
void move() {
PVector previous = this.prev_head.get();
PVector previous_copy = this.prev_head.get();
for(int i = 1; i < this.pos.length; i++) {
previous = pos[i];
pos[i] = previous_copy;
previous_copy = previous;
}
}
/* Autoexplicativo, pero esta es la función importante. Se llama en
el draw() principal y no aquí en update(). */
void search() {
this.controller.control();
}
void checkEatFood() {
if(this.pos[0].x == food_pos.x && this.pos[0].y == food_pos.y) {
this.eatsFood();
}
}
// Estira la serpiente después de comer
void eatsFood() {
if(this.pos.length == 1) {
this.pos = (PVector[])append(this.pos, new PVector(this.prev_head.x, this.prev_head.y));
} else {
this.pos = (PVector[])append(this.pos, new PVector(this.pos[this.pos.length - 1].x, this.pos[this.pos.length - 1].y));
}
}
/* Creo que las siguientes son autoexplicativas */
boolean ateFood() {
if(this.pos[0].x == food_pos.x && this.pos[0].y == food_pos.y) {
justAte = true;
return true;
}
return false;
}
void died() {
this.pos = new PVector[1];
this.pos[0] = new PVector(floor(random(horSqrs))*scl, floor(random(verSqrs))*scl);
}
void checkBoundaries() {
if(isOutsideWorld(pos[0])) {
this.died();
}
}
void checkCollBody() {
if(isInBody(this.pos[0])) {
this.died();
}
}
boolean isInBody(int x, int y) {
for(int i = 1; i < this.pos.length; i++) {
if(x*scl == this.pos[i].x && y*scl == this.pos[i].y) {
return true;
}
}
return false;
}
boolean isInBody(PVector position) {
return isInBody(int(position.x/scl), int(position.y/scl));
}
void square(float x, float y) {
noStroke();
fill(snakecol);
rect(x + 2, y + 2, scl - 3, scl - 3);
}
// Para realizar una copia virtual de la serpiente
Snake copy() {
Snake copy = new Snake(true);
copy.pos[0] = pos[0].copy();
for (int i = 1; i < pos.length; ++i) {
copy.pos = (PVector[])append(copy.pos, pos[i].copy());
}
copy.vel = vel.copy();
copy.prev_head = prev_head.copy();
return copy;
}
}