From: Jean Privat Date: Wed, 2 Aug 2017 13:30:28 +0000 (-0400) Subject: Merge: gamnit: misc fixes X-Git-Url: http://nitlanguage.org?hp=fcfc0701535b3816c8cb6e5a898f965f1a6b4523 Merge: gamnit: misc fixes Fix various bugs and issues related to gamnit : * Expose the previously private class `SpriteSet` for clients to access `time` and set `time_mod` (as intended). * Fix two bugs with animations: a div by zero in the shader that hid non-animated sprites on Android (a div by zero never crashes, but the return value is unspecified in OpenGL ES 2.0), and an array out of bounds error when an animation has a single frame. * Cache `GamnitDisplay::aspect_ratio` as it appears to be a performance bottleneck. * Fix the virtual gamepad not being interactive in Asteronits. * `UICamera::camera_to_ui` returns a `Point3d` that can be used directly as a `Sprite::center`. Pull-Request: #2532 Reviewed-by: Jean Privat --- diff --git a/contrib/asteronits/src/asteronits.nit b/contrib/asteronits/src/asteronits.nit index 1c148db..d7621de 100644 --- a/contrib/asteronits/src/asteronits.nit +++ b/contrib/asteronits/src/asteronits.nit @@ -89,6 +89,8 @@ redef class App redef fun accept_event(event) do + if super then return true + if event isa QuitEvent then exit 0 else if event isa KeyEvent then diff --git a/lib/a_star.nit b/lib/a_star.nit index cc0cba3..db80519 100644 --- a/lib/a_star.nit +++ b/lib/a_star.nit @@ -90,7 +90,7 @@ class Node # lifetime limited to evocation of `path_to` private var open: Bool = false - # Main functionnality, returns path from `self` to `dest` + # Main functionality, returns path from `self` to `dest` fun path_to(dest: N, max_cost: Int, context: PathContext): nullable AStarPath[N] do return path_to_alts(dest, max_cost, context, null) diff --git a/lib/gamnit/camera_control_linux.nit b/lib/gamnit/camera_control_linux.nit index 8c92e91..2aa5d48 100644 --- a/lib/gamnit/camera_control_linux.nit +++ b/lib/gamnit/camera_control_linux.nit @@ -23,7 +23,7 @@ redef class EulerCamera # Zoom factor, default at 1.2, higher means more reactive zoom effect var camera_zoom_mod = 1.2 is writable - # Scoll trigger button mask from SDL2 (1: left, 2: middle, 4: right) + # Scroll trigger button mask from SDL2 (1: left, 2: middle, 4: right) # # Set to 0 to deactivate the scrolling feature. var camera_pan_mask = 2 is writable diff --git a/lib/gamnit/cameras.nit b/lib/gamnit/cameras.nit index 688082b..c83ace3 100644 --- a/lib/gamnit/cameras.nit +++ b/lib/gamnit/cameras.nit @@ -225,14 +225,14 @@ class UICamera end # Convert the position `x, y` on screen, to UI coordinates - fun camera_to_ui(x, y: Numeric): Point[Float] + fun camera_to_ui(x, y: Numeric): Point3d[Float] do # FIXME this kind of method should use something like a canvas # instead of being hard coded on the display. var wx = x.to_f * width / display.width.to_f - position.x var wy = y.to_f * height / display.height.to_f - position.y - return new Point[Float](wx, -wy) + return new Point3d[Float](wx, -wy, 0.0) end # Center of the screen, from the point of view of the camera, at z = 0 diff --git a/lib/gamnit/flat/flat_core.nit b/lib/gamnit/flat/flat_core.nit index c8ffed4..dcb11f6 100644 --- a/lib/gamnit/flat/flat_core.nit +++ b/lib/gamnit/flat/flat_core.nit @@ -378,10 +378,10 @@ redef class App var ui_camera = new UICamera(app.display.as(not null)) is lazy # World sprites drawn as seen by `world_camera` - var sprites: Set[Sprite] = new SpriteSet + var sprites = new SpriteSet # UI sprites drawn as seen by `ui_camera`, over world `sprites` - var ui_sprites: Set[Sprite] = new SpriteSet + var ui_sprites = new SpriteSet # Main method to refine in clients to update game logic and `sprites` fun update(dt: Float) do end @@ -537,7 +537,7 @@ redef class App # Draw world sprites from `sprites` protected fun frame_core_world_sprites(display: GamnitDisplay) do - frame_core_sprites(display, sprites.as(SpriteSet), world_camera) + frame_core_sprites(display, sprites, world_camera) end # Draw UI sprites from `ui_sprites` @@ -546,7 +546,7 @@ redef class App # Reset only the depth buffer glClear gl_DEPTH_BUFFER_BIT - frame_core_sprites(display, ui_sprites.as(SpriteSet), ui_camera) + frame_core_sprites(display, ui_sprites, ui_camera) end end @@ -687,7 +687,7 @@ private class Simple2dProgram vec3 c; // coords float end = a_start + a_loops/a_fps*a_n_frames; - if (a_loops == -1.0 || time < end) { + if (a_fps != 0.0 && (a_loops == -1.0 || time < end)) { // in animation float frame = mod(floor((time-a_start)*a_fps), a_n_frames); v_coord = a_tex_coord + a_tex_diff*frame; @@ -875,26 +875,26 @@ redef class OffsetPoint3d end # Set of sprites sorting them into different `SpriteContext` -private class SpriteSet +class SpriteSet super HashSet[Sprite] - # Map texture then static vs dynamic to a `SpriteContext` - var contexts_map = new HashMap4[RootTexture, nullable RootTexture, Bool, Int, Array[SpriteContext]] - - # Contexts in `contexts_map`, sorted by draw order - var contexts_items = new Array[SpriteContext] - - # Sprites needing resorting in `contexts_map` - var sprites_to_remap = new Array[Sprite] - # Animation speed multiplier (0.0 to pause, 1.0 for normal speed, etc.) var time_mod = 1.0 is writable # Seconds elapsed since the launch of the program, in world time responding to `time_mod` var time = 0.0 + # Map texture then static vs dynamic to a `SpriteContext` + private var contexts_map = new HashMap4[RootTexture, nullable RootTexture, Bool, Int, Array[SpriteContext]] + + # Contexts in `contexts_map`, sorted by draw order + private var contexts_items = new Array[SpriteContext] + + # Sprites needing resorting in `contexts_map` + private var sprites_to_remap = new Array[Sprite] + # Add a sprite to the appropriate context - fun map_sprite(sprite: Sprite) + private fun map_sprite(sprite: Sprite) do assert sprite.context == null else print_error "Sprite {sprite} belongs to another SpriteSet" @@ -946,7 +946,7 @@ private class SpriteSet end # Remove a sprite from its context - fun unmap_sprite(sprite: Sprite) + private fun unmap_sprite(sprite: Sprite) do var context = sprite.context assert context != null @@ -957,10 +957,14 @@ private class SpriteSet end # Draw all sprites by all contexts - fun draw + private fun draw do # Remap sprites that may need to change context for sprite in sprites_to_remap do + + # Skip if it was removed from this set after being modified + if sprite.context != self then continue + unmap_sprite sprite map_sprite sprite end @@ -1211,8 +1215,12 @@ private class SpriteContext data[o+36] = tc[v*2+1] # a_tex_diff - var dx = animation.frames[1].texture_coords[0] - animation.frames[0].texture_coords[0] - var dy = animation.frames[1].texture_coords[1] - animation.frames[0].texture_coords[1] + var dx = 0.0 + var dy = 0.0 + if animation.frames.length > 1 then + dx = animation.frames[1].texture_coords[0] - animation.frames[0].texture_coords[0] + dy = animation.frames[1].texture_coords[1] - animation.frames[0].texture_coords[1] + end data[o+37] = dx data[o+38] = dy diff --git a/lib/gamnit/gamnit_linux.nit b/lib/gamnit/gamnit_linux.nit index b0c4241..b86f8e5 100644 --- a/lib/gamnit/gamnit_linux.nit +++ b/lib/gamnit/gamnit_linux.nit @@ -37,6 +37,7 @@ redef class App if sdl_event isa SDLWindowEvent and sdl_event.is_resized then display.width = sdl_event.data1 display.height = sdl_event.data2 + display.aspect_ratio = sdl_event.data1.to_f / sdl_event.data2.to_f on_resize display end @@ -47,6 +48,10 @@ redef class App end end +redef class GamnitDisplay + redef var aspect_ratio = super is lazy +end + # --- # Redef services from `sdl2::events`