42 #define TEXTURE_BACKDROP &tex2d[TEX_BACKDROP] |
42 #define TEXTURE_BACKDROP &tex2d[TEX_BACKDROP] |
43 |
43 |
44 #define BACKDROP_SCENE asc_window_scene(0) |
44 #define BACKDROP_SCENE asc_window_scene(0) |
45 #define MAIN_SCENE asc_window_scene(1) |
45 #define MAIN_SCENE asc_window_scene(1) |
46 |
46 |
47 static void destroy_textures(void) { |
|
48 asc_texture_destroy(tex2d, TEX2D_COUNT); |
|
49 } |
|
50 |
|
51 static void init_textures(void) { |
|
52 asc_texture_init_2d(tex2d, TEX2D_COUNT); |
|
53 asc_texture_from_file(TEXTURE_SHIP, "ship.png"); |
|
54 asc_texture_from_file(TEXTURE_BACKDROP, "backdrop.png"); |
|
55 asc_gl_context_add_cleanup_func(asc_active_glctx, destroy_textures); |
|
56 } |
|
57 |
|
58 static void update_fps_counter(AscBehavior *behavior) { |
|
59 asc_ptr_cast(AscText, node, behavior->node); |
|
60 static float last_fps = 0.f; |
|
61 if (fabsf(asc_context.frame_rate - last_fps) > 1) { |
|
62 last_fps = asc_context.frame_rate; |
|
63 asc_text_printf(node, "%.2f FPS", asc_context.frame_rate); |
|
64 } |
|
65 } |
|
66 |
|
67 static void tie_fps_counter_to_corner(AscBehavior *behavior) { |
|
68 // TODO: this should be replaced with some sort of UI layout manager |
|
69 AscSceneNode *node = behavior->node; |
|
70 if (asc_test_flag(node->flags, ASC_SCENE_NODE_GRAPHICS_UPDATED) || asc_active_window->resized) { |
|
71 asc_vec2u bottom_right = asc_active_window->dimensions; |
|
72 asc_vec2u text_size = ((AscText*)node)->dimension; |
|
73 asc_node_set_position2f(node, ASC_VEC2F( |
|
74 (int) bottom_right.x - (int) text_size.width - 10, |
|
75 (int) bottom_right.y - (int) text_size.height - 10 |
|
76 )); |
|
77 } |
|
78 } |
|
79 |
|
80 static void scale_backdrop(AscBehavior *behavior) { |
|
81 // scale the backdrop to the size of the window |
|
82 if (asc_active_window->resized) { |
|
83 asc_ptr_cast(AscSprite, sprite, behavior->node); |
|
84 asc_vec2u window_size = asc_active_window->dimensions; |
|
85 asc_sprite_set_size(sprite, window_size); |
|
86 } |
|
87 } |
|
88 |
|
89 static void create_backdrop(void) { |
|
90 AscSceneNode *node = asc_sprite( |
|
91 .texture = TEXTURE_BACKDROP, |
|
92 .texture_scale_mode = ASC_TEXTURE_SCALE_REPEAT |
|
93 ); |
|
94 asc_behavior_add(node, .func = scale_backdrop); |
|
95 asc_scene_add_node(BACKDROP_SCENE, node); |
|
96 } |
|
97 |
|
98 static void create_fps_counter(void) { |
|
99 asc_font(ASC_FONT_REGULAR, 12); |
|
100 asc_ink_rgb(255, 255, 255); |
|
101 AscSceneNode *node = asc_text(.name = "FPS Counter"); |
|
102 asc_behavior_add(node, .func = update_fps_counter, .interval = asc_seconds(1)); |
|
103 asc_behavior_add(node, tie_fps_counter_to_corner); |
|
104 asc_ui_add_node(node); |
|
105 } |
|
106 |
|
107 static void create_score_counter(void) { |
|
108 asc_font(ASC_FONT_BOLD, 16); |
|
109 asc_ink_rgb(0, 255, 0); |
|
110 AscSceneNode *node = asc_text( |
|
111 .name = "Score Counter", |
|
112 .x = 10, .y = 10, |
|
113 .text = "Score: 0" |
|
114 ); |
|
115 asc_ui_add_node(node); |
|
116 } |
|
117 |
|
118 enum MoveDirection { |
47 enum MoveDirection { |
119 MOVE_UP, |
48 MOVE_UP, |
120 MOVE_LEFT, |
49 MOVE_LEFT, |
121 MOVE_DOWN, |
50 MOVE_DOWN, |
122 MOVE_RIGHT |
51 MOVE_RIGHT |
124 |
53 |
125 static asc_transform rotations[4]; |
54 static asc_transform rotations[4]; |
126 static asc_vec2f directions[4]; |
55 static asc_vec2f directions[4]; |
127 |
56 |
128 typedef struct { |
57 typedef struct { |
129 AscSceneNode *sprite; |
|
130 enum MoveDirection direction; |
58 enum MoveDirection direction; |
131 } Spaceship; |
59 } Spaceship; |
132 |
60 |
133 static void turn_left(Spaceship *spaceship) { |
61 static void init_globals(void) { |
134 spaceship->direction = (spaceship->direction + 1) % 4; |
|
135 asc_node_set_rotation(spaceship->sprite, rotations[spaceship->direction]); |
|
136 } |
|
137 |
|
138 static void turn_right(Spaceship *spaceship) { |
|
139 spaceship->direction = (spaceship->direction + 3) % 4; |
|
140 asc_node_set_rotation(spaceship->sprite, rotations[spaceship->direction]); |
|
141 } |
|
142 |
|
143 static Spaceship *create_spaceship(void) { |
|
144 // TODO: this all belongs somewhere else, this is just quickly hacked into here for testing |
|
145 asc_transform_identity(rotations[MOVE_UP]); |
62 asc_transform_identity(rotations[MOVE_UP]); |
146 asc_transform_roll(rotations[MOVE_LEFT], asc_rad(-90)); |
63 asc_transform_roll(rotations[MOVE_LEFT], asc_rad(-90)); |
147 asc_transform_roll(rotations[MOVE_RIGHT], asc_rad(90)); |
64 asc_transform_roll(rotations[MOVE_RIGHT], asc_rad(90)); |
148 asc_transform_roll(rotations[MOVE_DOWN], asc_rad(180)); |
65 asc_transform_roll(rotations[MOVE_DOWN], asc_rad(180)); |
149 directions[MOVE_UP] = ASC_VEC2F(0, -1); |
66 directions[MOVE_UP] = ASC_VEC2F(0, -1); |
150 directions[MOVE_LEFT] = ASC_VEC2F(-1, 0); |
67 directions[MOVE_LEFT] = ASC_VEC2F(-1, 0); |
151 directions[MOVE_DOWN] = ASC_VEC2F(0, 1); |
68 directions[MOVE_DOWN] = ASC_VEC2F(0, 1); |
152 directions[MOVE_RIGHT] = ASC_VEC2F(1, 0); |
69 directions[MOVE_RIGHT] = ASC_VEC2F(1, 0); |
|
70 } |
|
71 |
|
72 static void destroy_textures(void) { |
|
73 asc_texture_destroy(tex2d, TEX2D_COUNT); |
|
74 } |
|
75 |
|
76 static void init_textures(void) { |
|
77 asc_texture_init_2d(tex2d, TEX2D_COUNT); |
|
78 asc_texture_from_file(TEXTURE_SHIP, "ship.png"); |
|
79 asc_texture_from_file(TEXTURE_BACKDROP, "backdrop.png"); |
|
80 asc_gl_context_add_cleanup_func(asc_active_glctx, destroy_textures); |
|
81 } |
|
82 |
|
83 static void update_fps_counter(AscBehavior *behavior) { |
|
84 asc_ptr_cast(AscText, node, behavior->node); |
|
85 static float last_fps = 0.f; |
|
86 if (fabsf(asc_context.frame_rate - last_fps) > 1) { |
|
87 last_fps = asc_context.frame_rate; |
|
88 asc_text_printf(node, "%.2f FPS", asc_context.frame_rate); |
|
89 } |
|
90 } |
|
91 |
|
92 static void tie_fps_counter_to_corner(AscBehavior *behavior) { |
|
93 // TODO: this should be replaced with some sort of UI layout manager |
|
94 AscSceneNode *node = behavior->node; |
|
95 if (asc_test_flag(node->flags, ASC_SCENE_NODE_GRAPHICS_UPDATED) || asc_active_window->resized) { |
|
96 asc_vec2u bottom_right = asc_active_window->dimensions; |
|
97 asc_vec2u text_size = ((AscText*)node)->dimension; |
|
98 asc_scene_node_set_position2f(node, ASC_VEC2F( |
|
99 (int) bottom_right.x - (int) text_size.width - 10, |
|
100 (int) bottom_right.y - (int) text_size.height - 10 |
|
101 )); |
|
102 } |
|
103 } |
|
104 |
|
105 static void scale_backdrop(AscBehavior *behavior) { |
|
106 // scale the backdrop to the size of the window |
|
107 if (asc_active_window->resized) { |
|
108 asc_ptr_cast(AscSprite, sprite, behavior->node); |
|
109 asc_vec2u window_size = asc_active_window->dimensions; |
|
110 asc_sprite_set_size(sprite, window_size); |
|
111 } |
|
112 } |
|
113 |
|
114 static void create_backdrop(void) { |
|
115 AscSceneNode *node = asc_sprite( |
|
116 .texture = TEXTURE_BACKDROP, |
|
117 .texture_scale_mode = ASC_TEXTURE_SCALE_REPEAT |
|
118 ); |
|
119 asc_behavior_add(node, .func = scale_backdrop); |
|
120 asc_scene_add_node(BACKDROP_SCENE, node); |
|
121 } |
|
122 |
|
123 static void create_fps_counter(void) { |
|
124 asc_font(ASC_FONT_REGULAR, 12); |
|
125 asc_ink_rgb(255, 255, 255); |
|
126 AscSceneNode *node = asc_text(.name = "FPS Counter"); |
|
127 asc_behavior_add(node, .func = update_fps_counter, .interval = asc_seconds(1)); |
|
128 asc_behavior_add(node, tie_fps_counter_to_corner); |
|
129 asc_ui_add_node(node); |
|
130 } |
|
131 |
|
132 static void create_score_counter(void) { |
|
133 asc_font(ASC_FONT_BOLD, 16); |
|
134 asc_ink_rgb(0, 255, 0); |
|
135 AscSceneNode *node = asc_text( |
|
136 .name = "Score Counter", |
|
137 .x = 10, .y = 10, |
|
138 .text = "Score: 0" |
|
139 ); |
|
140 asc_ui_add_node(node); |
|
141 } |
|
142 |
|
143 static void move_spaceship(AscBehavior *behavior) { |
|
144 AscSceneNode *node = behavior->node; |
|
145 Spaceship *spaceship = node->user_data; |
|
146 float speed = 32.f * asc_context.frame_factor; |
|
147 asc_vec2f movement = asc_vec2f_scale(directions[spaceship->direction], speed); |
|
148 asc_scene_node_move2f(node, movement); |
|
149 asc_scene_node_set_rotation(node, rotations[spaceship->direction]); |
|
150 } |
|
151 |
|
152 static Spaceship *create_spaceship(void) { |
153 AscSceneNode *sprite = asc_sprite( |
153 AscSceneNode *sprite = asc_sprite( |
154 .name = "Player", |
154 .name = "Player", |
155 .texture = TEXTURE_SHIP, |
155 .texture = TEXTURE_SHIP, |
156 .x = 250, |
156 .x = 250, |
157 .y = 300, |
157 .y = 300, |
158 .width = 64, |
158 .width = 32, |
159 .height = 64, |
159 .height = 32, |
160 .origin_x = 32, |
160 .origin_x = 16, |
161 .origin_y = 32, |
161 .origin_y = 16, |
162 ); |
162 ); |
163 asc_scene_add_node(MAIN_SCENE, sprite); |
163 asc_scene_add_node(MAIN_SCENE, sprite); |
164 // TODO: this is never freed at the moment |
164 asc_scene_node_allocate_data(sprite, sizeof(Spaceship)); |
165 Spaceship *ship = cxZallocDefault(sizeof(Spaceship)); |
165 asc_behavior_add(sprite, move_spaceship); |
166 ship->sprite = sprite; |
166 return sprite->user_data; |
167 return ship; |
|
168 } |
167 } |
169 |
168 |
170 static asc_rect update_viewport_for_window_resize(asc_vec2u window_size) { |
169 static asc_rect update_viewport_for_window_resize(asc_vec2u window_size) { |
171 // Compute scaling and offsets |
170 // Compute scaling and offsets |
172 unsigned viewport_size, offset_x = 0, offset_y = 0; |
171 unsigned viewport_size, offset_x = 0, offset_y = 0; |