Intro `create_gamnit` and `create_scene` to replace the use of `on_create` in gamnit. This change keeps separate the OpenGL setup in `create_gamnit`, from the world/menu creation in `create_scene`. This will allow support for reinitializing the OpenGL context when the EGL context is lost, which may happen on Android when the game goes in the background. It may also support creating a gamnit game separately from the main application.
Current gamnit games should still work despite the API change, but they will need updating to work with the incoming Android support.
Pull-Request: #2585
Reviewed-by: Romain Chanoir <romain.chanoir@viacesi.fr>
private var fx_explosion_ship = new Sound("sounds/explosion_ship.wav")
private var fx_explosion_asteroids = new Sound("sounds/explosion_asteroids.wav")
- redef fun on_create
+ redef fun create_scene
do
super
import asteronits
redef class App
- redef fun on_create
+ redef fun create_scene
do
super
# var pos: Point3d[Float] = ui_camera.top_left.offset(128.0, -128.0, 0.0)
# var ui_text = new TextSprites(font, pos)
#
-# redef fun on_create
+# redef fun create_scene
# do
# super
#
end
end
- redef fun on_create
+ redef fun create_scene
do
super
initialize_head_tracker
redef class App
- redef fun on_create
+ redef fun create_scene
do
- super
-
# Move the camera back a bit
world_camera.reset_height(10.0)
world_camera.near = 0.1
+ super
+ end
+
+ redef fun create_gamnit
+ do
+ super
+
# Cull the invisible triangles in the back of the geometries
glCullFace gl_BACK
for actor in actors do
for leaf in actor.model.leaves do
leaf.material.draw(actor, leaf, app.world_camera)
+ assert glGetError == gl_NO_ERROR else print_error "Gamnit error on material {leaf.material.class_name}"
end
end
perfs["gamnit depth actors"].add frame_core_depth_clock.lapse
# Toggle writing to the depth buffer for particles effects
glDepthMask false
- for system in particle_systems do system.draw
+ for system in particle_systems do
+ system.draw
+ assert glGetError == gl_NO_ERROR else print_error "OpenGL error in {system}"
+ end
glDepthMask true
perfs["gamnit depth particles"].add frame_core_depth_clock.lapse
# 3D model composed of `Mesh` and `Material`, loaded from the assets folder by default
#
-# Instances can be created at any time and must be loaded after or at the end of `on_create`.
+# Instances can be created at any time and must be loaded after or at the end of `create_scene`.
# If loading fails, the model is replaced by `placeholder_model`.
#
# ~~~
else
glDrawElements(mesh.draw_mode, mesh.indices.length, gl_UNSIGNED_SHORT, mesh.indices_c.native_array)
end
+
+ assert glGetError == gl_NO_ERROR
end
private fun setup_lights(actor: Actor, model: LeafModel, camera: Camera, program: BlinnPhongProgram)
private var perf_clock_shadow = new Clock is lazy
- redef fun on_create
+ redef fun create_gamnit
do
super
private var perf_clock_dynamic_resolution = new Clock is lazy
- redef fun on_create
+ redef fun create_scene
do
super
redef fun flip
do
+ assert glGetError == gl_NO_ERROR
+
+ assert egl_display.is_valid
+
egl_display.swap_buffers(window_surface)
end
end
# Bottom right corner
var corner = new Texture("corner.png")
- redef fun on_create
+ redef fun create_scene
do
super
redef class App
- # Texture, loaded automatically at `on_create`
+ # Texture, loaded in `create_scene`
var texture = new Texture("fighter.png")
# Sound effect, lazy loaded at first use
# Sprite, must be loaded in or after `on_create`
var sprite = new Sprite(texture, new Point3d[Float](0.0, 0.0, 0.0)) is lazy
- redef fun on_create
+ redef fun create_scene
do
super
# Scale the ship so it is approximately 5 world units wide.
sprite.scale = 5.0 / texture.width
- # Move the camera to show 10 world units on the Y axis at Z = 0.
+ # Move the camera to show 20 world units on the Y axis at Z = 0.
# The `sprite` should take approximately 1/4 of the height of the screen.
world_camera.reset_height 20.0
# Vertex data for the triangle
var vertex_array: VertexArray is noautoinit
- redef fun on_create
+ redef fun create_scene
do
super
# Second performance clock for smaller operations
private var perf_clock_sprites = new Clock is lazy
- redef fun on_create
+ redef fun create_gamnit
do
super
+ create_flat
+ end
+ # Prepare the flat framework services
+ fun create_flat
+ do
var display = display
assert display != null
glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_LINEAR)
glTexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_LINEAR)
end
+
+ sprites.reset
+ ui_sprites.reset
end
redef fun on_stop
do
+ super
+
# Clean up
simple_2d_program.delete
# draw
sprite_set.draw
+
+ assert glGetError == gl_NO_ERROR
end
# Draw world sprites from `sprites`
for sprite in sprites_to_remap do
# Skip if it was removed from this set after being modified
- if sprite.context != self then continue
+ if sprite.sprite_set != self then continue
unmap_sprite sprite
map_sprite sprite
for c in contexts_items do c.destroy
contexts_map.clear
contexts_items.clear
+ sprites_to_remap.clear
+ end
+
+ private fun reset
+ do
+ for sprite in self do
+ sprite.context = null
+ end
+
+ for c in contexts_items do c.destroy
+ contexts_map.clear
+ contexts_items.clear
+ sprites_to_remap.clear
+
+ for sprite in self do
+ map_sprite sprite
+ end
end
end
redef class App
- # Main `GamnitDisplay` initialized by `on_create`
+ # Main `GamnitDisplay` initialized by `create_gamnit`
var display: nullable GamnitDisplay = null
- redef fun on_create
+ # Hook to setup the OpenGL context: compiling shaders, creating VBO, reloading textures, etc.
+ #
+ # The gamnit services redefine this method to prepare optimizations and more.
+ # Clients may also refine this method to prepare custom OpenGL resources.
+ fun create_gamnit
do
- super
-
var display = new GamnitDisplay
display.setup
self.display = display
print "GL extensions: {glGetString(gl_EXTENSIONS)}"
end
+ # Hook for client programs to setup the scene
+ #
+ # Refine this method to build the game world or the main menu,
+ # creating instances of `Sprite` and `Actor` as needed.
+ #
+ # This method is called only once per execution of the program and it should
+ # be considered as the entry point of most game logic.
+ fun create_scene do end
+
# Core of the frame logic, executed only when the display is visible
#
# This method should be redefined by user modules to customize the behavior of the game.
accept_event gamnit_event
end
end
+
+ redef fun on_create
+ do
+ super
+ create_gamnit
+ create_scene
+ end
end
redef class GamnitDisplay
# Texture composed of pixels, loaded from the assets folder by default
#
# Most textures should be created with `App` (as attributes)
-# for the method `on_create` to load them.
+# for the method `create_scene` to load them.
#
# ~~~
# import gamnit::flat
# # Create the texture object, it will be loaded automatically
# var texture = new Texture("path/in/assets.png")
#
-# redef fun on_create()
+# redef fun create_scene()
# do
-# # Let `on_create` load the texture
+# # Let `create_scene` load the texture
# super
#
# # Use the texture
# end
# ~~~
#
-# Otherwise, they can be loaded and error checked explicitly after `on_create`.
+# Otherwise, they can be loaded and error checked explicitly after `create_scene`.
#
# ~~~nitish
# var texture = new Texture("path/in/assets.png")
#
# ~~~
# redef class App
-# redef fun on_create
+# redef fun create_scene
# do
# super
#