It is currently Wed Jul 06, 2011 7:24 pm

All times are UTC - 8 hours




 Page 1 of 1 [ 3 posts ] 
Author Message
 Post subject: Cavern flying side-scroller
PostPosted: Sat Mar 26, 2011 1:21 pm 

Joined: Sun Feb 27, 2011 11:32 am
Posts: 71
I was thinking of what games could be played with a single button and a sort of Defender style cavern flying game seemed doable. This simple game has no plot, no enemies, and no brakes.

Hit/hold the button to accelerate upwards at 1 G. Release the button to stop accelerating, but plan ahead so that you coast to apogee at the right time to avoid the cavern ceiling. Remember that dx/dt = v and dv/dt = a.

Video of the game: http://www.flickr.com/photos/osr/5562355052/


#include <pulse_os.h>
#include <pulse_types.h>
#include <app_resources.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define COLOR_BLACK   ((color24_t) { 0x00, 0x00, 0x00, 0 })
#define COLOR_GREEN   ((color24_t) { 0x00, 0xFF, 0x00, 0 })
#define COLOR_RED   ((color24_t) { 0xF0, 0x00, 0x00, 0 })

#define PLANE_X_MAX ((SCREEN_HEIGHT-10)*16)
#define PLANE_Y_MAX ((SCREEN_WIDTH-2)*16)

static uint8_t walls[2][SCREEN_HEIGHT];
static int16_t plane_x;
static int16_t plane_y;
static int8_t plane_v;
static unsigned plane_a;


static void
reset_game(void)
{
   srand(pulse_get_millis());
   memset(walls[0], 0, sizeof(walls[0]));
   memset(walls[1], SCREEN_WIDTH - 1, sizeof(walls[1]));

   plane_y = 3 * (PLANE_Y_MAX / 4);
   plane_x = PLANE_X_MAX;
   plane_v = 0;
   plane_a = 0;

   pulse_blank_canvas();
   pulse_oled_set_brightness(100);
}


void
main_app_handle_button_down(void)
{
   plane_a = pulse_get_millis();
}


void
main_app_handle_button_up(void)
{
   plane_a = 0;
}


static void
short_pulse()
{
   pulse_vibe_on();
   pulse_mdelay(100);
   pulse_vibe_off();
}


static uint8_t
new_point(
   int top
)
{
   // Generate a random point that doesn't hit the other side
   // or go off the screen to the bottom.
   const uint8_t w1 = walls[top][0];
   const uint8_t w2 = walls[!top][0];
   const uint8_t GAP = 30;

   while (1)
   {
      // 0-15
      int8_t n = rand() & 7;
      if (n == 0)
         continue;
      n -= 4;

      if (n < 0)
      {
         if (-n > w1)
            continue;
         if (top && w1 + n  - GAP <= w2)
            continue;
      } else
      if (n > 0)
      {
         if (n + w1 >= SCREEN_WIDTH)
            continue;
         if (!top && w1 + n + GAP >= w2)
            continue;
      }

      return w1 + n;
   }
}


static void
pulse_draw_row(
   uint8_t y,
   uint8_t x1,
   uint8_t x2,
   color24_t color
)
{
   if (x1 > x2)
   {
      uint8_t t = x1;
      x1 = x2;
      x2 = t;
   }

   pulse_set_draw_window(
      x1,
      y,
      x2,
      y
   );

   const uint8_t width = x2 - x1 + 1;

   for (uint8_t i = 0 ; i < width ; i++)
      pulse_draw_point24(color);
}


static void
move_walls(
   int top,
   uint8_t * const wall
)
{
   // Shuffle the wall to this side
   for (int i = SCREEN_HEIGHT-1 ; i >= 0 ; i--)
   {
      // Where was this pixel last screen draw
      const uint8_t w1 = wall[i];

      // Where this pixel will be this screen draw
      const uint8_t w2 = (i == 0)
         ? new_point(top)
         : wall[i-1];
      wall[i] = w2;

      if (!top)
      {
         // Adding/subtracting color
         // from the left side of the screen
         if (w1 < w2)
            pulse_draw_row(i, w1, w2, COLOR_GREEN);
         else
         if (w1 > w2)
            pulse_draw_row(i, w2, w1, COLOR_BLACK);
      } else
      {
         // Adding/subtracting color
         // from the right side of the screen
         if (w2 < w1)
            pulse_draw_row(i, w2, w1, COLOR_GREEN);
         else
         if (w2 > w1)
            pulse_draw_row(i, w1, w2, COLOR_BLACK);
      }
   }
}


static void
draw_plane(
   uint16_t x,
   uint16_t y,
   color24_t color
)
{
   x /= 16;
   y /= 16;

   pulse_set_draw_window(y, x, y + 1, x + 1);
   for (int i = 0 ; i < 4 ; i++)
      pulse_draw_point24(color);
}


static void
move_plane(void)
{
   const int16_t old_y = plane_y;
   const int16_t old_x = plane_x;

   plane_v -= 1; // gravity
   plane_v += plane_a ? 3 : 0; // boost

   if (plane_v > 100)
      plane_v = 100;
   else
   if (plane_v < -100)
      plane_v = -100;

   plane_y += plane_v;
   if (plane_y > PLANE_Y_MAX)
   {
      plane_y = PLANE_Y_MAX;
      plane_v = 0;
   } else
   if (plane_y < 0)
   {
      plane_y = 0;
      plane_v = 0;
   }

   if (plane_a)
   {
      plane_x -= 3; // boost forwards when they hold it down
      if (plane_x < 0)
         plane_x = 0;
   } else {
      plane_x++;
      if (plane_x > PLANE_X_MAX)
         plane_x = PLANE_X_MAX;
   }

   draw_plane(old_x, old_y, COLOR_BLACK);
   draw_plane(plane_x, plane_y, COLOR_RED);

   if (walls[0][plane_x/16] > plane_y / 16
   ||  walls[1][plane_x/16] < plane_y / 16)
   {
      short_pulse();
      reset_game();
   }
}



void
main_app_loop(void)
{
   static unsigned last_frame;
   unsigned now = pulse_get_millis();
   if (now - last_frame < 30)
      return;
   last_frame = now;

   move_walls(0, walls[0]);
   move_walls(1, walls[1]);
   move_plane();
}


void
main_app_init(void)
{
   reset_game();
}


void
main_app_handle_doz(void)
{
}


void
main_app_handle_hardware_update(
   enum PulseHardwareEvent event
)
{
}


Offline
 Profile  
 
 Post subject: Re: Cavern flying side-scroller
PostPosted: Sat Mar 26, 2011 2:15 pm 
User avatar

Joined: Fri Mar 04, 2011 8:54 pm
Posts: 82
Awesome game - very nice use of the one button interface.
Make sure to post this app in our app library on our site!



_________________
Image
Get the most out of your watch - http://www.inpulsewatch.com
Offline
 Profile  
 
 Post subject: Re: Cavern flying side-scroller
PostPosted: Sat Apr 09, 2011 3:03 pm 

Joined: Wed Apr 06, 2011 8:53 pm
Posts: 32
Awesome game, kudos! That's a perfect game for the watch! And thanks for making a movie too, makes it easy for everyone to see the awesomeness! :)


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 3 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: