def test_collision_polygon_verify_points(): # Those should be regular, non-colinear points assert core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0), core.LPoint3(0, 1, 0), core.LPoint3(0, 0, 1)]) assert core.CollisionPolygon.verify_points([core.LPoint3(10, 2, 8), core.LPoint3(7, 1, 3), core.LPoint3(5, 9, 6)]) assert core.CollisionPolygon.verify_points([core.LPoint3(3, -8, -7), core.LPoint3(9, 10, 8), core.LPoint3(7, 0, 10), core.LPoint3(-6, -2, 3)]) assert core.CollisionPolygon.verify_points([core.LPoint3(-1, -3, -5), core.LPoint3(10, 3, -10), core.LPoint3(-10, 10, -4), core.LPoint3(0, 1, -4), core.LPoint3(-9, -2, 0)]) with pytest.raises(TypeError): core.CollisionPolygon.verify_points([core.LPoint3(0, 0, 0), None])
def move_player(self): if not base.mouseWatcherNode.has_mouse() or self.debug_cam: return mousevec = base.mouseWatcherNode.get_mouse() near = p3d.LPoint3() far = p3d.LPoint3() base.camLens.extrude(mousevec, near, far) near = self.root_node.get_relative_point(base.cam, near) far = self.root_node.get_relative_point(base.cam, far) plane = p3d.Plane(p3d.LVector3.up(), p3d.LPoint3()) worldpos = p3d.LPoint3() if plane.intersects_line(worldpos, near, far): self.target.set_x(worldpos.x) self.target.set_y(worldpos.y)
def test_collision_polygon_verify_repeating_points(): # Repeating points cannot create a polygon assert not core.CollisionPolygon.verify_points( [core.LPoint3(1, 0, 0), core.LPoint3(1, 0, 0), core.LPoint3(0, 0, 1)]) assert not core.CollisionPolygon.verify_points([ core.LPoint3(3, 6, 1), core.LPoint3(1, 3, 5), core.LPoint3(9, 1, 2), core.LPoint3(1, 3, 5) ])
def test_collision_polygon_verify_colinear_points(): # Colinear points cannot create a polygon assert not core.CollisionPolygon.verify_points( [core.LPoint3(1, 2, 3), core.LPoint3(2, 3, 4), core.LPoint3(3, 4, 5)]) assert not core.CollisionPolygon.verify_points( [core.LPoint3(2, 1, 1), core.LPoint3(3, 2, 1), core.LPoint3(4, 3, 1)])
def process_input(self, input, dt, level): if self.locked: return if input.get_action('interact'): self.do_action() move_x = input.get_axis('move-horizontal') move_y = input.get_axis('move-vertical') if move_x: self.speed += move_x * self.acceleration * dt self.face(move_x) elif self.speed > 0: self.speed = max(0, self.speed - self.deceleration * dt) elif self.speed < 0: self.speed = min(0, self.speed + self.deceleration * dt) delta = core.Vec2(0, 0) if move_y: delta.y = move_y * dt * MOVE_Y_SPEED if self.speed != 0: if self.speed > self.max_speed: self.speed = self.max_speed elif self.speed < -self.max_speed: self.speed = -self.max_speed delta.x = self.speed * dt pos_changed = True self.move_control.set_play_rate(self.speed * self.facing * 4.0) if not self.move_control.playing: self.move_control.loop(False) self.move_sfx.play() elif self.move_control.playing: self.move_control.stop() self.move_sfx.stop() if delta.length_squared() > 0: old_pos = self.model.get_pos() new_pos = level.adjust_move(old_pos.xy, delta) self.model.set_pos(core.LPoint3(new_pos, old_pos.z))
def addFirefly(self): pos1 = p3dc.LPoint3(random.uniform(-50, 50), random.uniform(-100, 150), random.uniform(-10, 80)) dir = p3dc.LVector3(random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1)) dir.normalize() pos2 = pos1 + (dir * 20) fly = self.lightroot.attachNewNode(p3dc.PandaNode("fly")) glow = fly.attachNewNode(p3dc.PandaNode("glow")) dot = fly.attachNewNode(p3dc.PandaNode("dot")) color_r = 1.0 color_g = random.uniform(0.8, 1.0) color_b = min(color_g, random.uniform(0.5, 1.0)) fly.setColor(color_r, color_g, color_b, 1.0) fly.setShaderInput("lightcolor", (color_r, color_g, color_b, 1.0)) int1 = fly.posInterval(random.uniform(7, 12), pos1, pos2) int2 = fly.posInterval(random.uniform(7, 12), pos2, pos1) si1 = fly.scaleInterval(random.uniform(0.8, 1.5), p3dc.LPoint3(0.2, 0.2, 0.2), p3dc.LPoint3(0.2, 0.2, 0.2)) si2 = fly.scaleInterval(random.uniform(1.5, 0.8), p3dc.LPoint3(1.0, 1.0, 1.0), p3dc.LPoint3(0.2, 0.2, 0.2)) si3 = fly.scaleInterval(random.uniform(1.0, 2.0), p3dc.LPoint3(0.2, 0.2, 0.2), p3dc.LPoint3(1.0, 1.0, 1.0)) siseq = Sequence(si1, si2, si3) siseq.loop() siseq.setT(random.uniform(0, 1000)) seq = Sequence(int1, int2) seq.loop() self.spheremodel.instanceTo(glow) self.firefly.instanceTo(dot) glow.setScale(self.fireflysize * 1.1) glow.hide(p3dc.BitMask32(self.modelMask | self.plainMask)) dot.hide(p3dc.BitMask32(self.modelMask | self.lightMask)) dot.setColor(color_r, color_g, color_b, 1.0) self.fireflies.append(fly) self.sequences.append(seq) self.glowspheres.append(glow) self.scaleseqs.append(siseq)
def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setScale(0.01) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.light = ape.render().attachNewNode(p3dc.Spotlight("Spot")) self.light.node().setScene(ape.render()) self.light.node().setShadowCaster(True) self.light.node().showFrustum() self.light.node().getLens().setFov(40) self.light.node().getLens().setNearFar(10, 100) ape.render().setLight(self.light) self.alight = ape.render().attachNewNode(p3dc.AmbientLight("Ambient")) self.alight.node().setColor(p3dc.LVector4(0.2, 0.2, 0.2, 1)) ape.render().setLight(self.alight) # Important! Enable the shader generator. ape.render().setShaderAuto() # default values self.cameraSelection = 0 self.lightSelection = 0 self.incrementCameraPosition(0) self.incrementLightPosition(0)
def optimize_geom(gnode, gi): state = gnode.get_geom_state(gi) changed = False if gnode.get_geom(gi).bounds_type != core.BoundingVolume.BT_box: gnode.modify_geom(gi).bounds_type = core.BoundingVolume.BT_box changed = True tex_attrib = state.get_attrib(core.TextureAttrib) if not tex_attrib or tex_attrib.get_num_on_stages() == 0: # Nothing to optimize. return changed stage = tex_attrib.get_on_stage(0) tex = tex_attrib.get_on_texture(stage) if tex.wrap_u == core.SamplerState.WM_repeat: tex.wrap_u = core.SamplerState.WM_clamp changed = True if tex.wrap_v == core.SamplerState.WM_repeat: tex.wrap_v = core.SamplerState.WM_clamp changed = True img = core.PNMImage() img.set_color_space(core.CS_sRGB) tex.store(img) # Does the image have alpha? transp = state.get_attrib(core.TransparencyAttrib) if not img.has_alpha(): if transp and transp.mode != core.TransparencyAttrib.M_off: print(f"{tex.name}: turning off TransparencyAttrib") state = state.set_attrib( core.TransparencyAttrib.make(core.TransparencyAttrib.M_off)) gnode.set_geom_state(gi, state) return True else: # Nothing else to do. return changed # Crop the image. width, height = img.size crop_l = 0 for x in range(width): if any(img.get_alpha_val(x, y) > 0 for y in range(height)): crop_l = x break crop_r = width for x in reversed(range(crop_l, width)): if any(img.get_alpha_val(x, y) > 0 for y in range(height)): crop_r = x + 1 break crop_t = 0 for y in range(height): if any(img.get_alpha_val(x, y) > 0 for x in range(crop_l, crop_r)): crop_t = y break crop_b = height for y in reversed(range(crop_t, height)): if any(img.get_alpha_val(x, y) > 0 for x in range(crop_l, crop_r)): crop_b = y + 1 break # No cropping to be done. Is the image fully opaque, perhaps? if crop_l == 0 and crop_r == width and crop_t == 0 and crop_b == height: if is_image_fully_opaque(img): print(f"{tex.name}: fully opaque, removing alpha channel") img.remove_alpha() tex.load(img) tex.format = core.Texture.F_srgb tex.wrap_u = core.SamplerState.WM_clamp tex.wrap_v = core.SamplerState.WM_clamp tex.wrap_w = core.SamplerState.WM_clamp if transp and transp.mode != core.TransparencyAttrib.M_off: state = state.set_attrib( core.TransparencyAttrib.make( core.TransparencyAttrib.M_off)) gnode.set_geom_state(gi, state) return True # Premultiply alpha for higher-quality blending. transp = state.get_attrib(core.TransparencyAttrib) if transp and transp.mode == core.TransparencyAttrib.M_alpha: img.premultiply_alpha() prev_format = tex.format prev_sampler = core.SamplerState(tex.default_sampler) tex.load(img) tex.default_sampler = prev_sampler tex.format = prev_format # Check if this has binary alpha. if is_image_alpha_binary(img): print(f"{tex.name}: premultiplying alpha and setting to binary") state = state.set_attrib( core.TransparencyAttrib.make(core.TransparencyAttrib.M_binary)) else: print(f"{tex.name}: premultiplying alpha and setting to dual") #XXX there is no M_premultiplied_dual; this will have to suffice. state = state.set_attrib( core.TransparencyAttrib.make(core.TransparencyAttrib.M_dual)) gnode.set_geom_state(gi, state) changed = True # Make sure that the crop region is power-of-two, because why not. crop_w = crop_r - crop_l #pad_x = core.Texture.up_to_power_2(crop_w) - crop_w #pad_l = pad_x // 2 #pad_r = pad_x - pad_l #crop_l -= pad_l #crop_r += pad_r #if crop_l < 0: # crop_r += -crop_l # crop_l = 0 #crop_w = crop_r - crop_l #assert core.Texture.up_to_power_2(crop_w) == crop_w crop_h = crop_b - crop_t #pad_y = core.Texture.up_to_power_2(crop_h) - crop_h #pad_t = pad_y // 2 #pad_b = pad_y - pad_t #crop_t -= pad_t #crop_b += pad_b #crop_h = crop_b - crop_t #if crop_t < 0: # crop_b += -crop_t # crop_t = 0 #assert core.Texture.up_to_power_2(crop_h) == crop_h # Make sure the cropped region isn't bigger than the original image. if crop_w * crop_h >= width * height: print( f"{tex.name}: no need to crop, {width}×{height} is already its optimal size" ) return changed print( f"{tex.name}: cropping to a {crop_w}×{crop_h} region starting at {crop_l}×{crop_t}" ) new_img = core.PNMImage(crop_w, crop_h, img.num_channels, img.maxval, color_space=core.CS_sRGB) new_img.fill(0, 0, 0) if new_img.has_alpha(): new_img.alpha_fill(0) new_img.copy_sub_image(img, 0, 0, crop_l, crop_t, crop_w, crop_h) prev_sampler = core.SamplerState(tex.default_sampler) if is_image_fully_opaque(new_img): print(f"{tex.name}: fully opaque after crop, removing alpha channel") new_img.remove_alpha() tex.load(new_img) tex.format = core.Texture.F_srgb else: prev_format = tex.format tex.load(new_img) tex.format = prev_format tex.default_sampler = prev_sampler if crop_w < width: tex.wrap_u = core.SamplerState.WM_border_color elif tex.wrap_u == core.SamplerState.WM_repeat: tex.wrap_u = core.SamplerState.WM_clamp if crop_h < height: tex.wrap_v = core.SamplerState.WM_border_color elif tex.wrap_v == core.SamplerState.WM_repeat: tex.wrap_v = core.SamplerState.WM_clamp tex.border_color = (0, 0, 0, 0) assert tex.x_size == crop_w assert tex.y_size == crop_h # Now we need to either move the vertices or transform the UVs in order to # compensate for the cropped image. uv_pos = core.Vec2(crop_l / (width - 1.0), (height - crop_b) / (height - 1.0)) uv_scale = core.Vec2((crop_w - 1.0) / (width - 1.0), (crop_h - 1.0) / (height - 1.0)) vertex_data = gnode.modify_geom(gi).modify_vertex_data() uv_to_vtx = {} vtx_reader = core.GeomVertexReader(vertex_data, 'vertex') uv_reader = core.GeomVertexReader(vertex_data, stage.texcoord_name) while not vtx_reader.is_at_end() and not uv_reader.is_at_end(): uv = uv_reader.get_data2() vtx = core.LPoint3(vtx_reader.get_data3()) uv_to_vtx[tuple(uv)] = vtx vtx_reader = None uv_reader = None if (0, 0) in uv_to_vtx and (1, 1) in uv_to_vtx: # Crop the card itself, making it smaller, reducing overdraw. card_pos = uv_to_vtx[(0, 0)] card_size = uv_to_vtx[(1, 1)] - uv_to_vtx[(0, 0)] rewriter = core.GeomVertexRewriter(vertex_data, 'vertex') uv_reader = core.GeomVertexReader(vertex_data, stage.texcoord_name) while not rewriter.is_at_end() and not uv_reader.is_at_end(): vtx = rewriter.get_data3() uv = core.Point2(uv_reader.get_data2()) uv.componentwise_mult(uv_scale) uv += uv_pos rewriter.set_data3(uv[0] * card_size[0] + card_pos[0], uv[1] * card_size[1] + card_pos[1], vtx.z) rewriter = None # We can remove transparency if we cropped it to the opaque part. if tex.format == core.Texture.F_srgb: print("Removing transparency") state = state.set_attrib( core.TransparencyAttrib.make(core.TransparencyAttrib.M_off)) gnode.set_geom_state(gi, state) else: # Transform the UVs. rewriter = core.GeomVertexRewriter( gnode.modify_geom(gi).modify_vertex_data(), stage.get_texcoord_name()) while not rewriter.is_at_end(): uv = core.Point2(rewriter.get_data2()) uv -= uv_pos uv.x /= uv_scale.x uv.y /= uv_scale.y rewriter.set_data2(uv) rewriter = None return True
def test_collision_polygon_verify_not_enough_points(): # Less than 3 points cannot create a polygon assert not core.CollisionPolygon.verify_points([]) assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0)]) assert not core.CollisionPolygon.verify_points([core.LPoint3(1, 0, 0), core.LPoint3(0, 0, 1)])
def test_collision_polygon_setup_points(): # Create empty collision polygon polygon = core.CollisionPolygon(core.LVecBase3(0, 0, 0), core.LVecBase3(0, 0, 0), core.LVecBase3(0, 0, 0)) assert not polygon.is_valid() # Test our setup method against a few test cases for points in [ [core.LPoint3(-1, -3, -5), core.LPoint3(10, 3, -10), core.LPoint3(-10, 10, -4), core.LPoint3(0, 1, -4), core.LPoint3(-9, -2, 0)], [core.LPoint3(3, -8, -7), core.LPoint3(9, 10, 8), core.LPoint3(7, 0, 10), core.LPoint3(-6, -2, 3)], [core.LPoint3(1, 0, 0), core.LPoint3(0, 1, 0), core.LPoint3(0, 0, 1)], [core.LPoint3(10, 2, 8), core.LPoint3(7, 1, 3), core.LPoint3(5, 9, 6)] ]: polygon.setup_points(points) assert polygon.is_valid() assert polygon.get_num_points() == len(points) with pytest.raises(TypeError): polygon.setup_points([core.LPoint3(0, 0, 0), None, 1]) with pytest.raises(ValueError): polygon.setup_points([core.LPoint3(0, 0, 0)])
def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return # creating the offscreen buffer. winprops = p3dc.WindowProperties(size=(512, 512)) props = p3dc.FrameBufferProperties() props.setRgbColor(1) props.setAlphaBits(1) props.setDepthBits(1) LBuffer = ape.base().graphicsEngine.makeOutput( ape.base().pipe, "offscreen buffer", -2, props, winprops, p3dc.GraphicsPipe.BFRefuseWindow, ape.base().win.getGsg(), ape.base().win) self.buffer = LBuffer if not LBuffer: self.t = addTitle( "Shadow Demo: Video driver cannot create an offscreen buffer.") return Ldepthmap = p3dc.Texture() LBuffer.addRenderTexture(Ldepthmap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPDepthStencil) if ape.base().win.getGsg().getSupportsShadowFilter(): Ldepthmap.setMinfilter(p3dc.Texture.FTShadow) Ldepthmap.setMagfilter(p3dc.Texture.FTShadow) # Adding a color texture is totally unnecessary, but it helps with # debugging. Lcolormap = p3dc.Texture() LBuffer.addRenderTexture(Lcolormap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPColor) self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') self.inst_a = addInstructions(0.48, 'Something about A/Z and push bias') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0)) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapot.setShaderInput("texDisable", (1, 1, 1, 1)) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.accept('a', self.adjustPushBias, [1.1]) self.accept('z', self.adjustPushBias, [0.9]) self.LCam = ape.base().makeCamera(LBuffer) self.LCam.node().setScene(ape.render()) self.LCam.node().getLens().setFov(40) self.LCam.node().getLens().setNearFar(10, 100) # default values self.pushBias = 0.04 self.ambient = 0.2 self.cameraSelection = 0 self.lightSelection = 0 # setting up shader ape.render().setShaderInput('light', self.LCam) ape.render().setShaderInput('Ldepthmap', Ldepthmap) ape.render().setShaderInput('ambient', (self.ambient, 0, 0, 1.0)) ape.render().setShaderInput('texDisable', (0, 0, 0, 0)) ape.render().setShaderInput('scale', (1, 1, 1, 1)) # Put a shader on the Light camera. lci = p3dc.NodePath(p3dc.PandaNode("Light Camera Initializer")) lci.setShader(ape.loader().loadShader('shadows_caster.sha')) self.LCam.node().setInitialState(lci.getState()) # Put a shader on the Main camera. # Some video cards have special hardware for shadow maps. # If the card has that, use it. If not, use a different # shader that does not require hardware support. mci = p3dc.NodePath(p3dc.PandaNode("Main Camera Initializer")) if ape.base().win.getGsg().getSupportsShadowFilter(): mci.setShader(ape.loader().loadShader('shadows_shadow.sha')) else: mci.setShader( ape.loader().loadShader('shadows_shadow-nosupport.sha')) ape.base().cam.node().setInitialState(mci.getState()) self.incrementCameraPosition(0) self.incrementLightPosition(0) self.adjustPushBias(1.0)
def SquarePos(i): return p3dc.LPoint3((i % 8) - 3.5, int(i // 8) - 3.5, 0)
def start_move(self, dir): die = self.world.component_for_entity(self.player, components.Die) spatial = self.world.component_for_entity(self.player, components.Spatial) orig_pos = spatial.path.get_pos() orig_quat = spatial.path.get_quat() target_pos = spatial.path.get_pos() target_quat = spatial.path.get_quat() next_number = None vector = core.Vec2(0, 0) if dir == 'N': vector.y += 1 target_quat *= core.LRotation((1, 0, 0), -90) next_number = die.die.north_number elif dir == 'E': vector.x += 1 target_quat *= core.LRotation((0, 1, 0), 90) next_number = die.die.east_number elif dir == 'S': vector.y -= 1 target_quat *= core.LRotation((1, 0, 0), 90) next_number = die.die.south_number elif dir == 'W': vector.x -= 1 target_quat *= core.LRotation((0, 1, 0), -90) next_number = die.die.west_number z_scale = math.sqrt(0.5) - 0.5 target_pos.xy += vector x, y = int(target_pos[0]), int(target_pos[1]) type = self.world.level.get_tile(x, y) if not type.is_passable( next_number, self.world.toggle_state ) and not base.mouseWatcherNode.is_button_down('pause'): self.moving = True Sequence( Parallel( spatial.path.posInterval(0.05, orig_pos * 0.9 + target_pos * 0.1, blendType='easeInOut'), LerpFunctionInterval( lambda x: spatial.path.set_z(math.sin(x) * z_scale), 0.05, toData=math.pi * 0.1, blendType='easeInOut'), spatial.path.quatInterval(0.05, orig_quat * 0.9 + target_quat * 0.1, blendType='easeInOut'), ), Parallel( spatial.path.posInterval(0.05, orig_pos, blendType='easeIn'), LerpFunctionInterval( lambda x: spatial.path.set_z(math.sin(x) * z_scale), 0.05, fromData=math.pi * 0.1, toData=0, blendType='easeIn'), spatial.path.quatInterval(0.05, orig_quat, blendType='easeIn'), ), Func(self.stop_move)).start() if type.value and type.value in '123456': self.world.die_icon.flash((1, 0, 0, 1)) if base.impassable_sound: base.impassable_sound.play() return False # Build up the animation; the parallel gets prepended to the sequence parallel = [ spatial.path.posInterval(0.25, target_pos), LerpFunctionInterval( lambda x: spatial.path.set_z(math.sin(x) * z_scale), 0.25, toData=math.pi), spatial.path.quatInterval(0.25, target_quat), ] sequence = [] if type == TileType.ice: if base.slide_sound: sequence.append(Func(base.slide_sound.play)) else: if base.move_sound: sequence.append(Func(base.move_sound.play)) while type == TileType.ice: target_pos.xy += vector x, y = int(target_pos[0]), int(target_pos[1]) type = self.world.level.get_tile(x, y) if type == TileType.ice: sequence.append(spatial.path.posInterval(0.25, target_pos)) else: sequence.append( spatial.path.posInterval(0.5, target_pos, blendType='easeOut')) if type == TileType.teleporter: # Find other teleporter. x, y = int(target_pos[0]), int(target_pos[1]) others = set(self.world.teleporters) others.discard((x, y)) if others: new_xy = others.pop() new_target_pos = core.Point3(target_pos) new_target_pos.xy = new_xy tile1 = self.world.tiles[(x, y)] tile2 = self.world.tiles[new_xy] tile1_path = self.world.component_for_entity( tile1, components.Spatial).path tile2_path = self.world.component_for_entity( tile2, components.Spatial).path tile1_path.set_pos(new_target_pos) tile2_path.set_pos(target_pos) elevation = (0, 0, 0.65) time = max((target_pos.xy - new_target_pos.xy).length() * 0.15, 0.35) if base.transport_sound: sequence.append(Func(base.transport_sound.play)) sequence.append( Parallel( Sequence( spatial.path.posInterval(0.25, target_pos + elevation, blendType='easeInOut'), spatial.path.posInterval(time, new_target_pos + elevation, blendType='easeInOut'), spatial.path.posInterval(0.25, new_target_pos, blendType='easeInOut'), ), Sequence( tile2_path.posInterval(0.25, target_pos + elevation, blendType='easeInOut'), tile2_path.posInterval(time, new_target_pos + elevation, blendType='easeInOut'), tile2_path.posInterval(0.25, new_target_pos, blendType='easeInOut'), ), Sequence( tile1_path.posInterval(0.25, new_target_pos - elevation, blendType='easeInOut'), tile1_path.posInterval(time, target_pos - elevation, blendType='easeInOut'), tile1_path.posInterval(0.25, target_pos, blendType='easeInOut'), ), )) if self.button_tile: # Make the button raised again button_path = self.world.component_for_entity( self.button_tile, components.Spatial).path button_pos = core.LPoint3(button_path.get_pos()) button_pos.z = 0.07 parallel.append(button_path.posInterval(0.25, button_pos)) if self.cracked_tile: # Break away the cracked tile if base.collapse_sound: base.collapse_sound.play() self.world.add_component(self.cracked_tile, components.Falling(drag=5.0)) self.cracked_tile = None if type == TileType.exit: self.winning_move = True self.lock() if type == TileType.cracked: self.cracked_tile = self.world.tiles[(x, y)] self.world.level.remove_tile(x, y) del self.world.tiles[(x, y)] sequence.append(Func(base.crack_sound.play)) if type == TileType.button: button_tile = self.world.tiles[(x, y)] button_path = self.world.component_for_entity( button_tile, components.Spatial).path button_pos = core.LPoint3(button_path.get_pos()) button_pos.z = 0.0 parallel.append(button_path.posInterval(0.25, button_pos)) parallel.append(Sequence(Wait(0.1), Func(self.world.toggle_button))) if base.button_sound: parallel.append(Func(base.button_sound.play)) self.button_tile = button_tile if dir == 'N': die.die.rotate_north() elif dir == 'E': die.die.rotate_east() elif dir == 'S': die.die.rotate_south() elif dir == 'W': die.die.rotate_west() self.moving = True sequence.insert(0, Parallel(*parallel)) sequence.append(Func(self.stop_move)) Sequence(*sequence).start() self.world.on_player_move() return True