-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsim.py
executable file
·199 lines (159 loc) · 5.95 KB
/
sim.py
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env python3
# pylget for displaying to screen
from pyglet import window as p_window, app as p_app, clock as p_clock
from pyglet.window import key
from pymunk import Space # for rigid body physics
from pymunk.pyglet_util import DrawOptions # pymunk/pyglet interaction
from create_shapes import create_pentagon, create_triangle, create_segment
from create_shapes import create_circle, create_rect
from create_world import draw_border
from food import create_food
from bot import create_bot, move_bot
from rng import FOOD_X, FOOD_Y
import cfg
from sys import argv
def get_pymunk_space(gravity=(0, -9.807)):
'''returns a `space` where the physics happens'''
space = Space()
# gravity is represented by a tuple
# 0 acceleration in x-axis and -9.807 in y-axis
space.gravity = gravity
return space
# must be global because the @decorators work that way
window = p_window.Window(cfg.GW, cfg.GH, __file__, resizable=False)
space = get_pymunk_space(gravity=cfg.GRAVITY)
options = DrawOptions()
space.add(draw_border(cfg.GW, cfg.GH, thicc=cfg.BORDER_THICCNESS))
def begin_collision(arbiter, space, data):
s1 = arbiter.shapes[0]
s2 = arbiter.shapes[1]
if hasattr(s1.body, 'type') and hasattr(s2.body, 'type'):
types = [s1.body.type, s2.body.type]
if ('bot' in types):
print("begin_collision", arbiter.shapes, space, data) if cfg.DEBUG >= 2 else None
return True
def pre_collision(arbiter, space, data):
s1 = arbiter.shapes[0]
s2 = arbiter.shapes[1]
if hasattr(s1.body, 'type') and hasattr(s2.body, 'type'):
types = [s1.body.type, s2.body.type]
if ('bot' in types):
print("pre_collision", arbiter.shapes, space, data) if cfg.DEBUG >= 2 else None
return True
def post_collision(arbiter, space, data):
s1 = arbiter.shapes[0]
s2 = arbiter.shapes[1]
if hasattr(s1.body, 'type') and hasattr(s2.body, 'type'):
types = [s1.body.type, s2.body.type]
if ('bot' in types):
space.remove(s1.body, s1) if s1.body.type == 'food' else space.remove(s2.body, s2)
print("post_collision", arbiter.shapes, space, data) if cfg.DEBUG >= 2 else None
def separate_collision(arbiter, space, data):
s1 = arbiter.shapes[0]
s2 = arbiter.shapes[1]
if hasattr(s1.body, 'type') and hasattr(s2.body, 'type'):
types = [s1.body.type, s2.body.type]
if ('bot' in types):
print("separate_collision", arbiter.shapes, space, data) if cfg.DEBUG >= 2 else None
handler = space.add_default_collision_handler()
handler.begin = begin_collision
handler.pre_solve = pre_collision
handler.post_solve = post_collision
handler.separate = separate_collision
bot_body, bot_shape = create_bot()
def run():
'''
run the main loop for the game engine
'''
p_app.run()
def schedule(fun):
'''
given a function name
tell pyglet to call that function every 1/60 seconds
'''
p_clock.schedule_interval(fun, cfg.PY_STEP)
hold = False
last_move = cfg.MOVE_STOP
@window.event
def on_key_press(symbol, modifiers):
global hold, last_move
if symbol == key.UP:
hold = True
move_bot(bot_body, r=cfg.MOVE_UP)
last_move = cfg.MOVE_UP
elif symbol == key.DOWN:
move_bot(bot_body, r=cfg.MOVE_DOWN)
last_move = cfg.MOVE_DOWN
hold = True
elif symbol == key.RIGHT:
move_bot(bot_body, r=cfg.MOVE_RIGHT)
last_move = cfg.MOVE_RIGHT
hold = True
elif symbol == key.LEFT:
move_bot(bot_body, r=cfg.MOVE_LEFT)
last_move = cfg.MOVE_LEFT
hold = True
# else:
print("PRESS", "symbol", symbol, "modifier", modifiers)
@window.event
def on_key_release(symbol, modifiers):
global hold
if symbol in (key.UP, key.DOWN, key.LEFT, key.RIGHT):
hold = False
print("RELEASE", "symbol", symbol, "modifier", modifiers)
@window.event
def on_draw():
'''
stuff that happens when pyglet is drawing
'''
window.clear() # start with a clean window
space.debug_draw(options)
def main():
# make sure window and space are a thing
assert window
assert space
# initialize food at random places
for i in range(cfg.FOOD_COUNT):
food_body, food_shape = create_food()
x = FOOD_X[i]
y = FOOD_Y[i]
food_body.position = (x, y)
space.add(food_body, food_shape)
assert len(space.shapes) == cfg.FOOD_COUNT + 4 # 4 borders and 100 food
bot_body.position = (50, 100)
space.add(bot_body, bot_shape)
# 4 borders + 1 bot + 100 food
assert len(space.shapes) == cfg.FOOD_COUNT + 5 if cfg.DEBUG else None
print(len(space.shapes))
# do the update on 1/60th clock-ticks
def update(dt):
cfg.ITERATOR += 1
print(cfg.ITERATOR) if cfg.DEBUG >= 2 else None
quit(cfg.EXIT_SUCCESS) if cfg.ITERATOR >= cfg.MAX_STEPS else None
if cfg.DEBUG >= 3:
[print(type(shape), shape.body.position) for shape in space.shapes]
if hold:
move_bot(bot_body, r=last_move)
for shape in space.shapes:
x, y = shape.body.position.x, shape.body.position.y
x_is_outside = (x < (0-10) or x > (cfg.GW+10))
y_is_outside = (y < (0-10) or y > (cfg.GH+10))
if (x_is_outside or y_is_outside):
space.remove(shape, shape.body)
# else:
# if hasattr(shape.body, 'type'):
# move_bot(shape.body) if shape.body.type == 'bot' else None
return space.step(dt)
schedule(update)
run()
if __name__ == "__main__":
if (len(argv) >= 2 and (argv[1] == '-d' or argv[1] == '--debug')):
try:
cfg.DEBUG = int(argv[2])
except:
print(cfg.USAGE)
quit(cfg.EXIT_FAILURE)
print("DEBUG LEVEL 1 - ASSERT STATEMENTS") if cfg.DEBUG else None
print("DEBUG LEVEL 2 - PRINT STATEMENTS") if cfg.DEBUG >= 2 else None
print("DEBUG LEVEL 3 - LOTS OF PRINTS") if cfg.DEBUG >= 3 else None
main()