/usr/share/games/bouncy/rabbit.py is in bouncy 0.6.20071104-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | import math, os
import euclid, objloader, collide, objects
from OpenGL.GL import *
from OpenGL.GLUT import *
class Rabbit:
def load(cls):
cls.models = {}
for name in ['rabbit-sitting', 'rabbit-hopping', 'rabbit-landing',
'bump', 'rabbit-dig1', 'rabbit-dig2']:
obj = objloader.OBJ(os.path.join('data', '%s.obj'%name),
outline=objects.toon_program is not None)
cls.models[name] = obj
load = classmethod(load)
ST_SITTING = 'State: SITTING'
ST_HOPPING = 'State: HOPPING'
ST_DIGGING = 'State: DIGGING'
ST_EATING = 'State: EATING'
ST_UNDERGROUND = 'State: UNDERGROUND'
ST_SURFACING = 'State: SURFACING'
hit_offset = euclid.Vector3(0, 1.5, 0)
def __init__(self, position, rotation):
self.position = euclid.Point3(*position)
self.velocity = euclid.Vector3(0, 0, 0)
self.direction = rotation
self.model = self.models['rabbit-sitting']
self.state = self.ST_SITTING
self.hitbox = collide.AABox(self.position + self.hit_offset,
2, 3., 2)
self.hunger = {}
self.eating = None
def is_underground(self):
return (self.state is self.ST_UNDERGROUND or
self.state is self.ST_SURFACING)
def move(self, move):
if self.state is self.ST_HOPPING:
mag = abs(euclid.Vector2(self.velocity.x, self.velocity.z))
desired = euclid.Vector2(move.x, move.z).normalize()
result = desired * mag
self.velocity.x = result.x
self.velocity.z = result.y
if abs(result):
self.direction = math.atan2(result.x, result.y) * 180 / math.pi
return
if not abs(move):
return
impulse = move * .15
self.direction = math.atan2(move.x, move.z) * 180 / math.pi
if self.state is self.ST_SITTING:
self.model = self.models['rabbit-hopping']
self.state = self.ST_HOPPING
self.velocity += impulse + euclid.Vector3(0, .3, 0)
self.position += self.velocity
self.hitbox.c = self.position + self.hit_offset
elif self.state is self.ST_UNDERGROUND:
self.position += impulse
self.hitbox.c = self.position + self.hit_offset
def dig(self):
if self.state is self.ST_UNDERGROUND:
self.state = self.ST_SURFACING
self.surface_time = 0
elif self.state is self.ST_SITTING:
self.state = self.ST_DIGGING
self.model = self.models['rabbit-dig1']
self.dig_time = 0
def stop_dig(self):
if self.state is self.ST_DIGGING:
self.model = self.models['rabbit-sitting']
self.state = self.ST_SITTING
if self.state is self.ST_SURFACING:
self.state = self.ST_UNDERGROUND
def eat(self):
if self.state is self.ST_SITTING:
self.state = self.ST_EATING
self.eat_time = 0
def stop_eat(self):
if self.state is self.ST_EATING:
self.state = self.ST_SITTING
class RabbitFed:
pass
GRAVITY = 1.5/1000.
def animate(self, ts, level):
# gravity is a constant
self.velocity.y -= self.GRAVITY * ts
if self.state is self.ST_HOPPING:
if self.velocity.y <= 0:
self.model = self.models['rabbit-landing']
elif self.state is self.ST_EATING:
food = level.find_food(self.eat_sphere)
if food is not None and food.name.split('-')[0] in self.hunger:
food_name = food.name.split('-')[0]
if self.eating is not food:
self.eating = food
self.eat_time = 0
else:
self.eat_time += 1
if self.eat_time > 10:
self.eat_time = 0
level.eat_food(food)
self.hunger[food_name] = max(0,
self.hunger[food_name] - food.food_value)
for value in self.hunger.values():
if value > 0: break
else:
raise self.RabbitFed
elif self.state is self.ST_DIGGING:
self.dig_time += ts
if self.dig_time%300 > 100:
self.model = self.models['rabbit-dig2']
else:
self.model = self.models['rabbit-dig1']
if self.dig_time > 300:
self.dig_time += ts
r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
hole = r * euclid.Vector3(0., 0., 1.)
level.add_hole(self.position + hole)
if self.dig_time > 1200:
self.state = self.ST_UNDERGROUND
self.model = self.models['bump']
r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
bump = r * euclid.Vector3(0., 0., 1.)
self.position += bump
elif self.state is self.ST_UNDERGROUND:
# no collision detection
# TODO: collide with streams
return
elif self.state is self.ST_SURFACING:
self.surface_time += ts
if self.surface_time > 500:
r = euclid.Matrix4.new_rotatey(self.direction *
math.pi / 180)
hole = r * euclid.Vector3(0., 0., 1.)
level.add_hole(self.position + hole)
self.state = self.ST_SITTING
self.model = self.models['rabbit-sitting']
# move
old_pos = self.position.copy()
self.position = self.position + self.velocity
self.hitbox.c = self.position + self.hit_offset
# no level - simple animation
if level is None:
if self.position.y < 0:
self.state = self.ST_SITTING
self.position.y = 0
self.velocity = euclid.Vector3(0., 0., 0.)
return
# handle collision with the level
l = level.is_intersecting(self.hitbox)
vy = self.velocity.y
resting = False
if l:
# back-track
self.position = old_pos
self.hitbox.c = self.position + self.hit_offset
# now resolve
for hitbox in l:
self.hitbox.c, vmod = hitbox.resolve_collision(self.hitbox)
self.velocity = self.velocity * vmod
if vy < 0 and vmod.y == 0: resting = True
# now use velocity
self.hitbox.c = self.hitbox.c + self.velocity
# set rabbit center using hitbox offset
p = self.hitbox.c - self.hit_offset
self.position = euclid.Point3(p.x, p.y, p.z)
# if we're hopping but we've not moved then revert to sitting
if resting and self.state is self.ST_HOPPING:
self.velocity = euclid.Vector3(0., 0., 0.)
self.state = self.ST_SITTING
self.model = self.models['rabbit-sitting']
# place the eating sphere
r = euclid.Matrix4.new_rotatey(self.direction * math.pi / 180)
eat_vec = r * euclid.Vector3(0., 1., 2.)
self.eat_sphere = euclid.Sphere(self.position + eat_vec, 2.)
def render(self, show_collide=False):
if show_collide:
self.hitbox.render()
glPushMatrix()
glTranslate(self.eat_sphere.c.x, self.eat_sphere.c.y,
self.eat_sphere.c.z)
glColor(.5, .5, 1)
glutWireSphere(self.eat_sphere.r, 8, 8)
glPopMatrix()
else:
glPushMatrix()
glTranslate(self.position.x, self.position.y, self.position.z)
glRotate(self.direction, 0, 1, 0)
glCallList(self.model.gl_list)
glPopMatrix()
|