def update_moving(self): # 跳跃 if self.cur_state_idx == 2: return # 行走 prev_pos = math3d.vector(self.pos) self.moving_dir = self.get_user_input(g_moving_speed) if self.moving_dir.is_zero: return cur_moving = math3d.vector(self.moving_dir) self.up_ofs = math3d.vector(0, 0, 0) result = self.move() # 平走失败 if result.hit: # 尝试上楼 self.step_up() # 按移动方向移动 self.move_and_slide() result = self.step_down() # 踏空 或 可站立行走 if not result.hit or self.can_stand(self.pos, result.point, result.normal): return # 上楼失败,重置信息,直行 self.moving_dir = cur_moving self.pos = prev_pos self.no_up_slide = True self.move_and_slide() self.no_up_slide = False
def logic(self): if self._style == STYLE_FREELOOK: accel = math3d.vector(0, 0, 0) if self._is_forward: accel += self._camera.rotation_matrix.forward elif self._is_back: accel -= self._camera.rotation_matrix.forward elif self._is_left: accel -= self._camera.rotation_matrix.right elif self._is_right: accel += self._camera.rotation_matrix.right elif self._is_up: accel += self._camera.rotation_matrix.up elif self._is_down: accel -= self._camera.rotation_matrix.up top_speed = self._topspeed * 20.0 if self._fast_move else self._topspeed if not accel.is_zero: accel.normalize() self._velocity += accel * top_speed else: self._velocity -= self._velocity * 0.1 if self._velocity.length_sqr > top_speed * top_speed: self._velocity.normalize() self._velocity *= top_speed elif self._velocity.is_zero: self._velocity = math3d.vector(0, 0, 0) if self._velocity != math3d.vector(0, 0, 0): self._camera.position += self._velocity self.on_mouse_move()
def update_dropping(self): down = math3d.vector(0, - g_gravity, 0) self.moving_dir = self.get_user_input(g_drop_control_speed) self.moving_dir += down self.target_pos = self.pos + self.moving_dir result = self.sweep_test(self.pos, self.target_pos) if not result.hit: # 什么都没碰到,继续下落 self.pos = self.target_pos self.pos = self.pos return # 碰撞后是否可站立 standing_pos = math3d.vector(0, 0, 0) standing_pos.intrp(self.pos, self.target_pos, result.fraction) if self.can_stand(standing_pos, result.point, result.normal): self.update_collide_pos(result.fraction) # 进入行走态 self.update_collide_pos(result.fraction) self.cur_state_idx = 0 return # 进行滑动 result = self.slide(result) if result.hit: self.update_collide_pos(result.fraction) if self.can_stand(self.pos, result.point, result.normal): # 进入行走态 self.cur_state_idx = 0
def update_dropping(self): if self.state == tower_const.TOWER_STATE_MOVING: return down = math3d.vector(0, tower_const.GRAVITY, 0) cur_pos = math3d.vector(*self.pos) self.target_pos = cur_pos + down result = self.sweep_test(cur_pos, self.target_pos) if not result.hit: self.pos = self.target_pos.x, self.target_pos.y, self.target_pos.z self.set_state(tower_const.TOWER_STATE_DROPPING) return self.update_collide_pos(result.fraction) self.set_state(tower_const.TOWER_STATE_MOVING) global g_tower_init_pos init_z = g_tower_init_pos[1] init_z -= 5 g_tower_init_pos = (0, init_z, -100) cam = iworld3d.get_camera(tower_const.SCENE_LAYER) position = cam.position position.y -= 5 cam.position = position
def init(self): self.bill = None self.moving_dir = math3d.vector(0, 0, 0) # 移动方向 self.target_pos = math3d.vector(0, 0, 0) # 目标位置 self.is_dragging = False # 是否被鼠标拖动 self.mouse_pos = (0, 0) # 鼠标拖动位置 self.pre_mouse_pos = (0, 0) # 上一次鼠标的位置
def init(self): self.bill = None self.moving_dir = math3d.vector(0, 0, 0) self.target_pos = math3d.vector(0, 0, 0) self.pos = g_tower_init_pos[0], g_tower_init_pos[1], g_tower_init_pos[2] print "init pos", self.pos
def on_key_msg(self, msg, key): super(demo, self).on_key_msg(msg, key) if key == game.VK_W and msg==game.MSG_KEY_PRESSED: self.player.position += math3d.vector(0,0,5) elif key == game.VK_S and msg==game.MSG_KEY_PRESSED: self.player.position += math3d.vector(0,0,-5) elif key == game.VK_A and msg==game.MSG_KEY_PRESSED: self.player.position += math3d.vector(-5,0,0) elif key == game.VK_D and msg==game.MSG_KEY_PRESSED: self.player.position += math3d.vector(5,0,0)
def logic(self): if self.obj.position.x > 50: self.obj.position = math3d.vector(-50, self.obj.position.y, self.obj.position.z) else: self.obj.position = math3d.vector(self.obj.position.x + 1, self.obj.position.y, self.obj.position.z) if self.hp <= 0: self.hp = 1 else: self.set_hp(self.hp - 0.01)
def set_yawpitchdist(self, yaw, pitch, dist): if self._target: self._camera.position = self._target.position self._camera.rotation_matrix = self._target.rotation_matrix self._camera.yaw(yaw) self._camera.pitch(-pitch) self.move_relative(-dist) else: self._camera.set_placement( dist, math3d.vector(0, -1, -1), math3d.vector(0, 1, 0))
def update_plane_shadow(self): # 以player位置作射线,计算碰撞到哪个石头 p0 = self.pos coldata = iphy3d.hit_by_ray(eggyolk2_const.SCENE_LAYER, \ math3d.vector(p0[0], p0[1], p0[2]),\ math3d.vector(p0[0], p0[1]+10000, p0[2])) if coldata.hit: self.sprite.set_shadow_visible(True) self.sprite.clear_shadows() # 使用场景内置的0号光照 self.sprite.add_plane_shadow((coldata.normal, coldata.point), "light_1") else: self.sprite.set_shadow_visible(False)
def update_dropping(self): if self.state == eggyolk2_const.PLAYER_STATE_MOVING: return down = math3d.vector(0, eggyolk2_const.GRAVITY, 0) cur_pos = math3d.vector(*self.pos) self.target_pos = cur_pos + down result = self.sweep_test(cur_pos, self.target_pos) if not result.hit: # 没碰到东西,继续下落 self.pos = self.target_pos.x, self.target_pos.y, self.target_pos.z self.set_state(eggyolk2_const.PLAYER_STATE_DROPPING) return # 发现碰撞,更新位置 self.update_collide_pos(result.fraction) self.set_state(eggyolk2_const.PLAYER_STATE_MOVING)
def create_3d_ui(self, depth): ui = iworld3d.create_scene3d_ui(scn_file, depth = depth) model = iworld3d.model3d(gim_file, "", ui.get_ui_id()) fx = iworld3d.fx3d(fx_file, 1, layer_id = ui.get_ui_id()) model.posistion = math3d.vector(0.0, 0.0, 0.0) fx.position = math3d.vector(0.0, 20.0, 0.0) fx.restart() sce = ui.get_scene() camera = sce.get_camera() camera.set_placement( model.position + math3d.vector(0.0, 20.0, 45.0), math3d.vector(0, 0, -1), math3d.vector(0, 1, 0)) # 设置完场景信息后,更新一下 ui.update() return ui, model
def on_mouse_dragging(self): if not self.is_dragging: return # 下落的时候也可以拖拽 self.set_state(eggyolk2_const.PLAYER_STATE_MOVING) # 得到世界坐标 p, d = iworld3d.screen_to_world(eggyolk2_const.SCENE_LAYER, self.mouse_pos[0], self.mouse_pos[1]) d.normalize() position = p + d * ((-100 - p.z) / d.z) # 实际应用中需保证射线足够长,且摄像机在屏幕后方 # 此处为了保证射线在z轴方向的投影长度要大于100 # 这里position.z近似等于-100 pre_pos = self.pos pre_pos_v = math3d.vector(*pre_pos) # 计算长度 d = position - pre_pos_v # 避免最后一次移动带来的抖动和对0向量规范化 if d.length < 1: return d.normalize() p = pre_pos_v + d * 2 # 每帧向鼠标位置移动单位向量的距离 self.pos = p.x, p.y, p.z # 静态碰撞演示 if self.anything_collision(): self.pos = pre_pos
def get_user_input(self, speed): dir = math3d.vector(0, 0, 0) # 前进 if idemo_glb.API.is_press_key(game.VK_W): dir.z += 1.0 if self.cur_state_idx == 0: self.cur_anim_idx = 1 if idemo_glb.API.is_press_key(game.VK_S): dir.z -= 1.0 if self.cur_state_idx == 0: self.cur_anim_idx = 2 if idemo_glb.API.is_press_key(game.VK_A): dir.x -= 1.0 if self.cur_state_idx == 0: self.cur_anim_idx = 1 if idemo_glb.API.is_press_key(game.VK_D): dir.x += 1.0 if self.cur_state_idx == 0: self.cur_anim_idx = 1 if dir.is_zero: return dir if dir.z < 0: speed *= 0.5 dir = self.camera.rotation_matrix.mulvec3x3(dir) dir.y = 0 dir.normalize() dir *= speed return dir
def update_collide_pos(self, fraction): cur_pos = math3d.vector(*self.pos) length = (cur_pos - self.target_pos).length moved = length * fraction if moved < eggyolk2_const.MARGIN: return cur_pos.intrp(cur_pos, self.target_pos, (moved - eggyolk2_const.MARGIN) / length) self.pos = cur_pos.x, cur_pos.y, cur_pos.z
def __init__(self, scene): self.pre_anim_idx = 4 self.cur_anim_idx = 4 # 状态 self.state = [ self.update_moving, self.update_dropping, self.update_jumpping, ] self.cur_state_idx = 1 # 初始态 self.sce = scene self.avt_mgr = iworld3d.avatar_mgr() self.model = self.avt_mgr.create("me", idemo_glb.API.get_my_avatar()) # 圆柱体 size = self.model.bounding_box * model_scale self.col_obj = iphy3d.col_cylinder(size.x, size.y) self.col_obj.add_to_scene3d() self._pos = init_pos self.base_pos = math3d.vector(0, size.y, 0) #avt的基点在脚下 self.pos = self._pos self.model.scale = (model_scale, model_scale, model_scale) self.model.anim_rate = 1.5 #速度播快一点 self.camera = self.sce.get_camera() self.camera.set_placement( self.pos + math3d.vector(0.0, 45.0, 45.0), math3d.vector(0, -1, -1), math3d.vector(0, 1, 0)) self.moving_dir = math3d.vector(0, 0, 0) self.jump_begin = math3d.vector(0, 0, 0) # 起跳位置 self.target_pos = math3d.vector(0, 0, 0) self.up_ofs = None # 上提高度 self.no_up_slide = False self.play_animation() self.is_debug_draw = False
def manual_stop(self): if self._style == STYLE_FREELOOK: self._is_forward = False self._is_back = False self._is_left = False self._is_right = False self._is_up = False self._is_down = False self._velocity = math3d.vector(0, 0, 0)
def on_key_msg(self, msg, key): super(demo, self).on_key_msg(msg, key) if msg == game.MSG_KEY_PRESSED: if key >= game.VK_NUM0 and key <= game.VK_NUM9: # 相机控制演示 # 小键盘46表示相机沿x轴左右平移 # 小键盘28表示相机沿y轴上下平移 # 小键盘13表示相机沿z轴前后平移 # 小键盘79表示相机沿y轴左右旋转 # 小键盘5表示相机对准主角小蛋黄 # 小键盘0表示相机恢复初始状态 cam = iworld3d.get_camera(SCENE_LAYER) position = cam.position if key == game.VK_NUM4: position.x -= CAMERA_MOVE_STEP elif key == game.VK_NUM6: position.x += CAMERA_MOVE_STEP elif key == game.VK_NUM8: position.y -= CAMERA_MOVE_STEP elif key == game.VK_NUM2: position.y += CAMERA_MOVE_STEP elif key == game.VK_NUM1: position.z += CAMERA_MOVE_STEP elif key == game.VK_NUM3: position.z -= CAMERA_MOVE_STEP elif key == game.VK_NUM7: self.cam_rot -= 1 cam.rotate_to_xyz(y=self.cam_rot*math.pi/200) elif key == game.VK_NUM9: self.cam_rot += 1 cam.rotate_to_xyz(y=self.cam_rot*math.pi/200) elif key == game.VK_NUM5: cam.look_at(self.player.position) elif key == game.VK_NUM0: # 还原位置 position = math3d.vector(0,0,0) forward = math3d.vector(0,0,-1) up = math3d.vector(0,-1,0) # 还原旋转矩阵 # 演示rotation_matrix的用法 cam.rotation_matrix = math3d.matrix.make_orient(forward, up) # 实际上此用法等同于这个接口 #iworld3d.set_camera_placement(SCENE_LAYER, position, forward, up) cam.position = position
def step_up(self): self.up_ofs = math3d.vector(0, g_climb_height, 0) self.target_pos = self.pos + self.up_ofs result = self.sweep_test(self.pos, self.target_pos) if not result.hit: self.pos = self.target_pos return temp = self.pos self.update_collide_pos(result.fraction) self.up_ofs = self.pos - temp
def moving(self): if self.moving_dir.is_zero: return cur_pos = math3d.vector(*self.pos) self.target_pos = cur_pos + self.moving_dir result = self.sweep_test(cur_pos, self.target_pos) if not result.hit: self.pos = self.target_pos.x, self.target_pos.y, self.target_pos.z return self.update_collide_pos(result.fraction)
def move(self): if self.moving_dir.is_zero: return self.model.rotation_matrix = math3d.matrix.make_orient(self.moving_dir, math3d.vector(0.0, 1.0, 0.0)) self.target_pos = self.pos + self.moving_dir result = self.sweep_test(self.pos, self.target_pos) if not result.hit: # 可行 self.pos = self.target_pos return result
def step_down(self): # 正常来说,你让角色最大能跨的高度,取负就是它能踏下最大高度 down = math3d.vector(0, g_climb_height, 0) self.target_pos = self.pos - self.up_ofs - down result = self.sweep_test(self.pos, self.target_pos) if not result.hit: self.pos = self.target_pos self.cur_state_idx = 1 return result self.update_collide_pos(result.fraction) return result
def logic(self): if self.player: self.camera.position = self.player.position-CAMERA_DISTANCE self.camera.look_at(self.player.position) # 主角位置设为场景自动加载的中心点 self.scn.set_view_position(self.player.position) # 动态添加外围的场景 x = int(self.player.position.x+200)/400 y = int(self.player.position.z+200)/400 if (abs(x)>=2 or abs(y)>=2) and (x, y) not in self.scene_pos: self.scene_pos[(x, y)] = 1 self.scn.auto_load_scene(SCN_FILE%4, math3d.vector(x*400, 0, y*400))
def __init__(self, camera): self._camera = camera self._target = None self._orbiting = False self._zooming = False self._topspeed = 2 self._velocity = math3d.vector(0, 0, 0) self._is_forward = False self._is_back = False self._is_left = False self._is_right = False self._is_up = False self._is_down = False self._fast_move = False self._style = STYLE_FREELOOK
def __init__(self): super(demo, self).__init__() iworld3d.init() self.scn = iworld3d.create_scene3d(SCN_FILE%1) self.player = iworld3d.model3d("idemos/res/eggyolk/world3d/xiaodanhuang.gim") self.player.pos = (0,0,0) self.camera = iworld3d.get_camera(iworld3d.NO_2D_LAYER) # 预先生成如下分块的场景,其中1为刚生成的self.scn # 323 # 212 # 323 for offset in ((-1,0), (1,0), (0,-1), (0,1)): self.scn.auto_load_scene(SCN_FILE%2, math3d.vector(offset[0]*400, 0, offset[1]*400)) for offset in ((1,1), (-1,1), (1,-1), (-1,-1)): self.scn.auto_load_scene(SCN_FILE%3, math3d.vector(offset[0]*400, 0, offset[1]*400)) self.scn.set_view_range(100) # 如果设置1000,则一开始就能看到所有场景 # self.scn.set_view_range(1000) self.scene_pos = {} # 记录动态加载的场景位置
def on_mouse_move(self): if not g_mouse_dragging: idemo_glb.API.show_sys_mouse(True) idemo_glb.API.lock_cursor_pos(False) return dx, dy = idemo_glb.API.lock_cursor_pos(True) prev_rotation = self.camera.rotation_matrix dis = (self.camera.position - self.pos).length self.camera.yaw(dx * g_pixel_to_angel, iworld3d.SPACE_TYPE_WORLD) self.camera.pitch(dy * g_pixel_to_angel) pos = self.pos - self.camera.rotation_matrix.forward * dis # 控制相机高度 if pos.y < 2.0 or pos.y > 60.0: self.camera.rotation_matrix = prev_rotation return self.camera.set_placement(pos, self.camera.rotation_matrix.forward, math3d.vector(0, 1, 0))
def flash_to_pos(self, screen_x, screen_y): # 得到世界坐标 p, d = iworld3d.screen_to_world(eggyolk2_const.SCENE_LAYER, screen_x, screen_y) d.normalize() position = p + d * ((-100 - p.z) / d.z) # 实际应用中需保证射线足够长,且摄像机在屏幕后方 # 此处为了保证射线在z轴方向的投影长度要大于100 # 这里position.z近似等于-100 # 射线起点为摄像机的位置,终点为屏幕上物体所在层的位置 if not self.is_ray_hit(math3d.vector(0, 0, 0), position): # 为了避免边缘的碰撞,再做一次static_test pre_pos = self.pos self.pos = position.x, position.y, position.z if self.anything_collision(): self.pos = pre_pos return self.set_state(eggyolk2_const.PLAYER_STATE_DROPPING)
def update_jumpping(self): up = math3d.vector(0, 2.0 * g_gravity, 0) self.moving_dir = self.get_user_input(g_jumpping_control_speed) self.moving_dir += up self.target_pos = self.pos + self.moving_dir result = self.sweep_test(self.pos, self.target_pos) if not result.hit: self.pos = self.target_pos if self.pos.y - self.jump_begin.y > g_max_jump_height: self.pos.y = self.jump_begin.y + g_max_jump_height self.cur_state_idx = 1 self.pos = self.pos return self.update_collide_pos(result.fraction) if self.can_stand(self.pos, result.point, result.normal): self.cur_state_idx = 0 else: self.cur_state_idx = 1
def rand_init(self): x = random.random() * 50 * random.choice([-1, 1]) y = random.random() * 40 * random.choice([-1, 1]) z = (random.random() + 0.2) * -200 self.obj.position = math3d.vector(x, y, z)
def can_stand(self, pos, hit_point, normal): if pos.y - hit_point.y < g_climb_height: return False if normal.dot(math3d.vector(0.0, 1.0, 0.0)) < 0.5: return False return True