#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
/* button setup for Arduboy Production */
uint8_t pin_up = D1;
uint8_t pin_down = D2;
uint8_t pin_fire = D0;
#define ST_FP 4
/* object types */
struct _st_ot_struct
{
/*
missle and hit:
bit 0: player missle and trash
bit 1: trash, which might hit the player
*/
uint8_t missle_mask; /* this object is a missle: it might destroy something if the target is_hit_fn says so */
uint8_t hit_mask; /* if missle_mask & hit_mask is != 0 then the object can be destroyed */
uint8_t points;
uint8_t draw_fn;
uint8_t move_fn;
/* ST_MOVE_FN_NONE, ST_MOVE_FN_X_SLOW */
uint8_t destroy_fn; /* object can be destroyed by a missle (e.g. a missle from the space ship) */
/* ST_DESTROY_FN_NONE, ST_DESTROY_FN_SPLIT */
uint8_t is_hit_fn; /* is hit procedure */
/* ST_IS_HIT_FN_NONE, ST_IS_HIT_BBOX */
uint8_t fire_fn;
/* ST_FIRE_FN_NONE, ST_FIRE_FN_X_LEFT */
};
typedef struct _st_ot_struct st_ot;
/*
objects, which are visible at the play area
*/
struct _st_obj_struct
{
uint8_t ot; /* object type: zero means, object is not used */
int8_t tmp; /* generic value, used by ST_MOVE_IMPLODE */
/* absolute position */
/* LCD pixel position is x>>ST_FP and y>>ST_FP */
int16_t x, y;
int8_t x0,y0,x1,y1; /* object outline in pixel, reference point is at 0,0 */
};
typedef struct _st_obj_struct st_obj;
#define ST_DRAW_NONE 0
#define ST_DRAW_BBOX 1
#define ST_DRAW_TRASH1 2
#define ST_DRAW_PLAYER1 3
#define ST_DRAW_TRASH2 4
#define ST_DRAW_PLAYER2 5
#define ST_DRAW_PLAYER3 6
#define ST_DRAW_GADGET 7
#define ST_DRAW_BACKSLASH 8
#define ST_DRAW_SLASH 9
#define ST_DRAW_BIG_TRASH 10
#define ST_MOVE_NONE 0
#define ST_MOVE_X_SLOW 1
#define ST_MOVE_PX_NORMAL 2
#define ST_MOVE_PX_FAST 3
#define ST_MOVE_PLAYER 4
#define ST_MOVE_PY 5
#define ST_MOVE_NY 6
#define ST_MOVE_IMPLODE 7
#define ST_MOVE_X_FAST 8
#define ST_MOVE_WALL 9
#define ST_MOVE_NXPY 10
#define ST_MOVE_NXNY 11
#define ST_IS_HIT_NONE 0
#define ST_IS_HIT_BBOX 1
#define ST_IS_HIT_WALL 2
#define ST_DESTROY_NONE 0
#define ST_DESTROY_DISAPPEAR 1
#define ST_DESTROY_TO_DUST 2
#define ST_DESTROY_GADGET 3
#define ST_DESTROY_PLAYER 4
#define ST_DESTROY_PLAYER_GADGETS 5
#define ST_DESTROY_BIG_TRASH 6
#define ST_FIRE_NONE 0
#define ST_FIRE_PLAYER1 1
#define ST_FIRE_PLAYER2 2
#define ST_FIRE_PLAYER3 3
#define ST_OT_WALL_SOLID 1
#define ST_OT_BIG_TRASH 2
#define ST_OT_MISSLE 3
#define ST_OT_TRASH1 4
#define ST_OT_PLAYER 5
#define ST_OT_DUST_PY 6
#define ST_OT_DUST_NY 7
#define ST_OT_TRASH_IMPLODE 8
#define ST_OT_TRASH2 9
#define ST_OT_PLAYER2 10
#define ST_OT_PLAYER3 11
#define ST_OT_GADGET 12
#define ST_OT_GADGET_IMPLODE 13
#define ST_OT_DUST_NXPY 14
#define ST_OT_DUST_NXNY 15
/*================================================================*/
/* graphics object */
/*================================================================*/
u8g2_t *st_u8g2;
u8g2_uint_t u8g_height_minus_one;
#define ST_AREA_HEIGHT (st_u8g2->height - 8)
#define ST_AREA_WIDTH (st_u8g2->width)
/*================================================================*/
/* object types */
/*================================================================*/
const st_ot st_object_types[] U8X8_PROGMEM =
{
/* 0: empty object type */
{ 0, 0, 0, ST_DRAW_NONE, ST_MOVE_NONE, ST_DESTROY_DISAPPEAR, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* 1: wall, player will be destroyed */
{ 2, 1, 30, ST_DRAW_BBOX, ST_MOVE_WALL, ST_DESTROY_DISAPPEAR, ST_IS_HIT_WALL, ST_FIRE_NONE },
/* ST_OT_BIG_TRASH (2) */
{ 2, 1, 0, ST_DRAW_BIG_TRASH, ST_MOVE_X_SLOW, ST_DESTROY_BIG_TRASH, ST_IS_HIT_BBOX, ST_FIRE_NONE },
/* 3: simple space ship (player) missle */
{ 1, 0, 0, ST_DRAW_BBOX, ST_MOVE_PX_FAST, ST_DESTROY_DISAPPEAR, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_TRASH1 (4): trash */
{ 2, 1, 0, ST_DRAW_TRASH1, ST_MOVE_X_SLOW, ST_DESTROY_TO_DUST, ST_IS_HIT_BBOX, ST_FIRE_NONE },
/* ST_OT_PLAYER (5): player space ship */
{ 0, 2, 0, ST_DRAW_PLAYER1, ST_MOVE_PLAYER, ST_DESTROY_PLAYER, ST_IS_HIT_BBOX, ST_FIRE_PLAYER1 },
/* ST_OT_DUST_PY (6): Last part of trash */
{ 0, 0, 0, ST_DRAW_BBOX, ST_MOVE_PY, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_DUST_NY (7): Last part of trash */
{ 0, 0, 0, ST_DRAW_BBOX, ST_MOVE_NY, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_TRASH_IMPLODE (8): trash was hit */
{ 0, 0, 5, ST_DRAW_TRASH1, ST_MOVE_IMPLODE, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_TRASH2 (9): trash */
{ 2, 1, 0, ST_DRAW_TRASH2, ST_MOVE_X_SLOW, ST_DESTROY_TO_DUST, ST_IS_HIT_BBOX, ST_FIRE_NONE },
/* ST_OT_PLAYER2 (10): player space ship+1x enhancement */
{ 0, 2, 0, ST_DRAW_PLAYER2, ST_MOVE_PLAYER, ST_DESTROY_PLAYER_GADGETS, ST_IS_HIT_BBOX, ST_FIRE_PLAYER2 },
/* ST_OT_PLAYER3 (11): player space ship+2x enhancement */
{ 0, 2, 0, ST_DRAW_PLAYER3, ST_MOVE_PLAYER, ST_DESTROY_PLAYER_GADGETS, ST_IS_HIT_BBOX, ST_FIRE_PLAYER3 },
/* ST_OT_GADGET (12): adds enhancements */
{ 0, 1, 0, ST_DRAW_GADGET, ST_MOVE_X_FAST, ST_DESTROY_GADGET, ST_IS_HIT_BBOX, ST_FIRE_NONE },
/* ST_OT_GADGET_IMPLODE (13) */
{ 0, 0, 20, ST_DRAW_GADGET, ST_MOVE_IMPLODE, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_DUST_NXPY (14): Last part of trash */
{ 0, 0, 0, ST_DRAW_BACKSLASH, ST_MOVE_NXPY, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
/* ST_OT_DUST_NXNY (15): Last part of trash */
{ 0, 0, 0, ST_DRAW_SLASH, ST_MOVE_NXNY, ST_DESTROY_NONE, ST_IS_HIT_NONE, ST_FIRE_NONE },
};
/*================================================================*/
/* list of all objects on the screen */
/*================================================================*/
/* use AVR RAMEND constant to derive the number of allowed objects */
#if RAMEND < 0x300
#define ST_OBJ_CNT 25
#else
//#define ST_OBJ_CNT 45
#define ST_OBJ_CNT 60
#endif
st_obj st_objects[ST_OBJ_CNT];
/*================================================================*/
/* about players space ship*/
/*================================================================*/
/* player position */
uint8_t st_player_pos;
/* points */
#define ST_POINTS_PER_LEVEL 25
uint16_t st_player_points;
uint16_t st_player_points_delayed;
uint16_t st_highscore = 0;
/*================================================================*/
/* overall game state */
/*================================================================*/
#define ST_STATE_PREPARE 0
#define ST_STATE_IPREPARE 1
#define ST_STATE_GAME 2
#define ST_STATE_END 3
#define ST_STATE_IEND 4
uint8_t st_state = ST_STATE_PREPARE;
/*================================================================*/
/* game difficulty */
/*================================================================*/
uint8_t st_difficulty = 1;
#define ST_DIFF_VIS_LEN 30
#define ST_DIFF_FP 5
uint16_t st_to_diff_cnt = 0;
/*================================================================*/
/* bitmaps */
/*================================================================*/
const uint8_t st_bitmap_player1[] =
{
/* 01100000 */ 0x060,
/* 11111000 */ 0x0f8,
/* 01111110 */ 0x07e,
/* 11111000 */ 0x0f8,
/* 01100000 */ 0x060
};
const uint8_t st_bitmap_player2[] =
{
/* 01100000 */ 0x060,
/* 01111100 */ 0x078,
/* 01100000 */ 0x060,
/* 11100000 */ 0x0e0,
/* 11111000 */ 0x0f8,
/* 01111110 */ 0x07e,
/* 11111000 */ 0x0f8,
/* 01100000 */ 0x060
};
const uint8_t st_bitmap_player3[] =
{
/* 01100000 */ 0x060,
/* 01111100 */ 0x078,
/* 01100000 */ 0x060,
/* 11100000 */ 0x0e0,
/* 11111000 */ 0x0f8,
/* 01111110 */ 0x07e,
/* 11111000 */ 0x0f8,
/* 11100000 */ 0x0e0,
/* 01100000 */ 0x060,
/* 01111100 */ 0x078,
/* 01100000 */ 0x060
};
const uint8_t st_bitmap_trash_5x5_1[] =
{
/* 01110000 */ 0x070,
/* 11110000 */ 0x0f0,
/* 11111000 */ 0x0f8,
/* 01111000 */ 0x078,
/* 00110000 */ 0x030,
};
const uint8_t st_bitmap_trash_5x5_2[] =
{
/* 00110000 */ 0x030,
/* 11111000 */ 0x0f8,
/* 11111000 */ 0x0f8,
/* 11110000 */ 0x0f0,
/* 01110000 */ 0x070,
};
const uint8_t st_bitmap_trash_7x7[] =
{
/* 00111000 */ 0x038,
/* 01111100 */ 0x07c,
/* 11111100 */ 0x0fc,
/* 11111110 */ 0x0fe,
/* 11111110 */ 0x0fe,
/* 01111110 */ 0x07e,
/* 01111000 */ 0x078,
};
const uint8_t st_bitmap_gadget[] =
{
/* 01110000 */ 0x070,
/* 11011000 */ 0x0d8,
/* 10001000 */ 0x088,
/* 11011000 */ 0x0d8,
/* 01110000 */ 0x070,
};
/*================================================================*/
/* forward definitions */
/*================================================================*/
uint8_t st_rnd(void) U8X8_NOINLINE;
static st_obj *st_GetObj(uint8_t objnr) U8X8_NOINLINE;
uint8_t st_GetMissleMask(uint8_t objnr);
uint8_t st_GetHitMask(uint8_t objnr);
int8_t st_FindObj(uint8_t ot) U8X8_NOINLINE;
void st_ClrObjs(void) U8X8_NOINLINE;
int8_t st_NewObj(void) U8X8_NOINLINE;
uint8_t st_CntObj(uint8_t ot);
uint8_t st_CalcXY(st_obj *o) U8X8_NOINLINE;
void st_SetXY(st_obj *o, uint8_t x, uint8_t y) U8X8_NOINLINE;
void st_FireStep(uint8_t is_auto_fire, uint8_t is_fire) U8X8_NOINLINE;
void st_InitTrash(uint8_t x, uint8_t y, int8_t dir);
void st_NewGadget(uint8_t x, uint8_t y);
void st_NewPlayerMissle(uint8_t x, uint8_t y) ;
void st_NewTrashDust(uint8_t x, uint8_t y, int ot);
void st_NewTrashDustAreaArgs(int16_t x, int16_t y, int ot);
void st_SetupPlayer(uint8_t objnr, uint8_t ot);
/*================================================================*/
/* utility functions */
/*================================================================*/
char st_itoa_buf[12];
char *st_itoa(unsigned long v)
{
volatile unsigned char i = 11;
st_itoa_buf[11] = '\0';
while( i > 0)
{
i--;
st_itoa_buf[i] = (v % 10)+'0';
v /= 10;
if ( v == 0 )
break;
}
return st_itoa_buf+i;
}
uint8_t st_rnd(void)
{
return rand();
}
/*
for the specified index number, return the object
*/
static st_obj *st_GetObj(uint8_t objnr)
{
return st_objects+objnr;
}
/*
check, if this is a missle-like object (that is, can this object destroy something else)
*/
uint8_t st_GetMissleMask(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
return u8x8_pgm_read(&(st_object_types[o->ot].missle_mask));
}
/*
check, if this is a missle-like object (that is, can this object destroy something else)
*/
uint8_t st_GetHitMask(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
return u8x8_pgm_read(&(st_object_types[o->ot].hit_mask));
}
/*
search an empty object
*/
int8_t st_FindObj(uint8_t ot)
{
int8_t i;
for( i = 0; i < ST_OBJ_CNT; i++ )
{
if ( st_objects[i].ot == ot )
return i;
}
return -1;
}
/*
delete all objects
*/
void st_ClrObjs(void)
{
int8_t i;
for( i = 0; i < ST_OBJ_CNT; i++ )
st_objects[i].ot = 0;
}
/*
search an empty object
*/
int8_t st_NewObj(void)
{
int8_t i;
for( i = 0; i < ST_OBJ_CNT; i++ )
{
if ( st_objects[i].ot == 0 )
return i;
}
return -1;
}
/*
count number of objectes of the provided type
st_CntObj(0) will return the number of empty objects, that means if
st_CntObj(0) > 0 then st_NewObj() will return a valid index
*/
uint8_t st_CntObj(uint8_t ot)
{
uint8_t i;
uint8_t cnt = 0;
for( i = 0; i < ST_OBJ_CNT; i++ )
{
if ( st_objects[i].ot == ot )
cnt++;
}
return cnt;
}
/*
calculate the pixel coordinates of the reference point of an object
return rhe x value
*/
uint8_t st_px_x, st_px_y; /* pixel within area */
uint8_t st_CalcXY(st_obj *o)
{
//st_obj *o = st_GetObj(objnr);
st_px_y = o->y>>ST_FP;
st_px_x = o->x>>ST_FP;
return st_px_x;
}
void st_SetXY(st_obj *o, uint8_t x, uint8_t y)
{
o->x = ((int16_t)x) << ST_FP;
o->y = ((int16_t)y) << ST_FP;
}
/*
calculate the object bounding box and place it into some global variables
*/
int16_t st_bbox_x0, st_bbox_y0, st_bbox_x1, st_bbox_y1;
void st_CalcBBOX(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
st_bbox_x0 = (uint16_t)(o->x>>ST_FP);
st_bbox_x1 = st_bbox_x0;
st_bbox_x0 += o->x0;
st_bbox_x1 += o->x1;
st_bbox_y0 = (uint16_t)(o->y>>ST_FP);
st_bbox_y1 = st_bbox_y0;
st_bbox_y0 += o->y0;
st_bbox_y1 += o->y1;
}
/*
clip bbox with the view window. requires a call to st_CalcBBOX
return 0, if the bbox is totally outside the window
*/
uint8_t st_cbbox_x0, st_cbbox_y0, st_cbbox_x1, st_cbbox_y1;
uint8_t st_ClipBBOX(void)
{
if ( st_bbox_x0 >= ST_AREA_WIDTH )
return 0;
if ( st_bbox_x0 >= 0 )
st_cbbox_x0 = (uint16_t)st_bbox_x0;
else
st_cbbox_x0 = 0;
if ( st_bbox_x1 < 0 )
return 0;
if ( st_bbox_x1 < ST_AREA_WIDTH )
st_cbbox_x1 = (uint16_t)st_bbox_x1;
else
st_cbbox_x1 = ST_AREA_WIDTH-1;
if ( st_bbox_y0 >= ST_AREA_HEIGHT )
return 0;
if ( st_bbox_y0 >= 0 )
st_cbbox_y0 = (uint16_t)st_bbox_y0;
else
st_cbbox_y0 = 0;
if ( st_bbox_y1 < 0 )
return 0;
if ( st_bbox_y1 < ST_AREA_HEIGHT )
st_cbbox_y1 = (uint16_t)st_bbox_y1;
else
st_cbbox_y1 = ST_AREA_HEIGHT-1;
return 1;
}
/*================================================================*/
/* universal member functions */
/*================================================================*/
uint8_t st_IsOut(uint8_t objnr)
{
st_CalcBBOX(objnr);
if ( st_bbox_x0 >= ST_AREA_WIDTH )
return 1;
if ( st_bbox_x1 < 0 )
return 1;
if ( st_bbox_y0 >= ST_AREA_HEIGHT )
return 1;
if ( st_bbox_y1 < 0 )
return 1;
return 0;
}
void st_Disappear(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
st_player_points += u8x8_pgm_read(&(st_object_types[o->ot].points));
o->ot = 0;
}
/*================================================================*/
/* type dependent member functions */
/*================================================================*/
void st_Move(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
switch(u8x8_pgm_read(&(st_object_types[o->ot].move_fn)))
{
case ST_MOVE_NONE:
break;
case ST_MOVE_X_SLOW:
o->x -= (1<<ST_FP)/8;
o->x -= st_difficulty;
o->y += (int16_t)o->tmp;
if ( o->y >= ((ST_AREA_HEIGHT-1) << ST_FP) || o->y <= 0 )
o->tmp = - o->tmp;
break;
case ST_MOVE_X_FAST:
o->x -= (1<<ST_FP)/2;
o->y += (int16_t)o->tmp;
if ( o->y >= ((ST_AREA_HEIGHT-1) << ST_FP) || o->y <= 0 )
o->tmp = - o->tmp;
break;
case ST_MOVE_PX_NORMAL:
o->x += (1<<ST_FP)/4;
break;
case ST_MOVE_PX_FAST:
o->x += (1<<ST_FP);
break;
case ST_MOVE_PLAYER:
o->y = st_player_pos<<ST_FP;
break;
case ST_MOVE_PY:
o->y += 3*ST_FP;
break;
case ST_MOVE_NY:
o->y -= 3*ST_FP;
break;
case ST_MOVE_NXPY:
o->y += 3*ST_FP;
o->x -= 3*ST_FP;
break;
case ST_MOVE_NXNY:
o->y -= 3*ST_FP;
o->x -= 3*ST_FP;
break;
case ST_MOVE_IMPLODE:
o->tmp++;
if ( (o->tmp & 0x03) == 0 )
{
if ( o->x0 != o->x1 )
o->x0++;
else
st_Disappear(objnr);
}
break;
case ST_MOVE_WALL:
o->x -= 1;
o->x -= (st_difficulty>>1);
break;
}
}
void st_DrawBBOX(uint8_t objnr)
{
uint8_t y0, y1;
/*st_obj *o = st_GetObj(objnr);*/
st_CalcBBOX(objnr);
if ( st_ClipBBOX() == 0 )
return;
/* st_cbbox_x0, st_cbbox_y0, st_cbbox_x1, st_cbbox_y1; */
// w = st_cbbox_x1-st_cbbox_x0;
// w++;
// h = st_cbbox_y1-st_cbbox_y0;
// h++;
//dog_SetVLine(st_cbbox_x0, st_cbbox_y0, st_cbbox_y1);
//dog_SetVLine(st_cbbox_x1, st_cbbox_y0, st_cbbox_y1);
//dog_SetHLine(st_cbbox_x0, st_cbbox_x1, st_cbbox_y0);
//dog_SetHLine(st_cbbox_x0, st_cbbox_x1, st_cbbox_y1);
u8g2_SetDrawColor(st_u8g2, 1);
y0 = u8g_height_minus_one - st_cbbox_y0;
y1 = u8g_height_minus_one - st_cbbox_y1;
u8g2_DrawFrame(st_u8g2, st_cbbox_x0, y1, st_cbbox_x1-st_cbbox_x0+1, y0-y1+1);
//dog_SetBox(st_cbbox_x0, st_cbbox_y0, st_cbbox_x1, st_cbbox_y1);
/*
if ( o->ot == ST_OT_PLAYER )
{
dog_DrawStr(0, 26, font_4x6, st_itoa(st_cbbox_y0));
dog_DrawStr(10, 26, font_4x6, st_itoa(st_cbbox_y1));
}
*/
}
#ifdef FN_IS_NOT_IN_USE
void st_DrawFilledBox(uint8_t objnr)
{
st_CalcBBOX(objnr);
if ( st_ClipBBOX() == 0 )
return;
/* st_cbbox_x0, st_cbbox_y0, st_cbbox_x1, st_cbbox_y1; */
dog_SetBox(st_cbbox_x0, st_cbbox_y0, st_cbbox_x1, st_cbbox_y1);
}
#endif
void st_DrawBitmap(uint8_t objnr, const uint8_t * bm, uint8_t w, uint8_t h)
{
/* st_obj *o = st_GetObj(objnr); */
st_CalcBBOX(objnr);
/* result is here: int16_t st_bbox_x0, st_bbox_y0, st_bbox_x1, st_bbox_y1 */
//dog_SetBitmapP(st_bbox_x0,st_bbox_y1,bm,w,h);
u8g2_DrawBitmap(st_u8g2, st_bbox_x0, u8g_height_minus_one - st_bbox_y1, (w+7)/8, h, bm);
}
void st_DrawObj(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
switch(u8x8_pgm_read(&(st_object_types[o->ot].draw_fn)))
{
case ST_DRAW_NONE:
break;
case ST_DRAW_BBOX:
st_DrawBBOX(objnr);
break;
case ST_DRAW_TRASH1:
st_DrawBitmap(objnr, st_bitmap_trash_5x5_1,o->x1-o->x0+1, 5);
break;
case ST_DRAW_TRASH2:
st_DrawBitmap(objnr, st_bitmap_trash_5x5_2,o->x1-o->x0+1, 5);
break;
case ST_DRAW_BIG_TRASH:
st_DrawBitmap(objnr, st_bitmap_trash_7x7,o->x1-o->x0+1, 7);
break;
case ST_DRAW_PLAYER1:
st_DrawBitmap(objnr, st_bitmap_player1,7,5);
break;
case ST_DRAW_PLAYER2:
st_DrawBitmap(objnr, st_bitmap_player2,7,8);
break;
case ST_DRAW_PLAYER3:
st_DrawBitmap(objnr, st_bitmap_player3,7,11);
break;
case ST_DRAW_GADGET:
/* could use this proc, but... */
/* st_DrawBitmap(objnr, st_bitmap_gadget,o->x1-o->x0+1, 5); */
/* ... this one looks also funny. */
st_DrawBitmap(objnr, st_bitmap_gadget,5,5);
break;
case ST_DRAW_BACKSLASH:
{
uint8_t x;
uint8_t y;
x = st_CalcXY(o);
y = st_px_y;
// dog_SetPixel(x,y);
// x++; y--;
// dog_SetPixel(x,y);
// x++; y--;
// dog_SetPixel(x,y);
u8g2_SetDrawColor(st_u8g2, 1);
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
x++; y--;
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
x++; y--;
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
}
break;
case ST_DRAW_SLASH:
{
uint8_t x;
uint8_t y;
x = st_CalcXY(o);
y = st_px_y;
// dog_SetPixel(x,y);
// x++; y++;
// dog_SetPixel(x,y);
// x++; y++;
// dog_SetPixel(x,y);
u8g2_SetDrawColor(st_u8g2, 1);
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
x++; y++;
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
x++; y++;
u8g2_DrawPixel(st_u8g2, x, u8g_height_minus_one - y);
}
break;
}
}
uint8_t st_IsHitBBOX(uint8_t objnr, uint8_t x, uint8_t y)
{
st_CalcBBOX(objnr);
if ( st_ClipBBOX() == 0 )
return 0; /* obj is outside (not visible) */
if ( x < st_cbbox_x0 )
return 0;
if ( x > st_cbbox_x1 )
return 0;
if ( y < st_cbbox_y0 )
return 0;
if ( y > st_cbbox_y1 )
return 0;
return 1;
}
void st_Destroy(uint8_t objnr)
{
int8_t nr;
st_obj *o = st_GetObj(objnr);
switch(u8x8_pgm_read(&(st_object_types[o->ot].destroy_fn)))
{
case ST_DESTROY_NONE: /* only usefull for missels or walls which stay alife */
break;
case ST_DESTROY_DISAPPEAR: /* this should be the default operation */
st_Disappear(objnr);
break;
case ST_DESTROY_GADGET:
nr = st_FindObj(ST_OT_PLAYER2);
if ( nr >= 0 )
st_SetupPlayer(nr, ST_OT_PLAYER3);
else
{
nr = st_FindObj(ST_OT_PLAYER);
if ( nr >= 0 )
st_SetupPlayer(nr, ST_OT_PLAYER2);
}
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_PY);
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_NY);
o->ot = ST_OT_GADGET_IMPLODE;
o->tmp = 0;
break;
case ST_DESTROY_TO_DUST:
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_PY);
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_NY);
o->ot = ST_OT_TRASH_IMPLODE;
o->tmp = 0;
break;
case ST_DESTROY_BIG_TRASH:
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_PY);
st_NewTrashDustAreaArgs(o->x, o->y, ST_OT_DUST_NY);
st_InitTrash((o->x>>ST_FP)-1, (o->y>>ST_FP)+3, 2+(st_rnd()&3));
st_InitTrash((o->x>>ST_FP)-2, (o->y>>ST_FP)-3, -2-(st_rnd()&3));
st_Disappear(objnr);
break;
case ST_DESTROY_PLAYER:
st_Disappear(objnr);
st_state = ST_STATE_END;
o->tmp = 0;
break;
case ST_DESTROY_PLAYER_GADGETS:
/* o->ot = ST_OT_PLAYER; */
st_SetupPlayer(objnr, ST_OT_PLAYER);
break;
}
}
/*
check if the target (objnr) has been hit.
st_IsHit() must also destroy the target.
return value:
0: do not destroy the missle
1: destroy the missle
*/
uint8_t st_IsHit(uint8_t objnr, uint8_t x, uint8_t y, uint8_t missle_mask)
{
uint8_t hit_mask = st_GetHitMask(objnr);
st_obj *o;
if ( (hit_mask & missle_mask) == 0 )
return 0;
o = st_GetObj(objnr);
switch(u8x8_pgm_read(&(st_object_types[o->ot].is_hit_fn)))
{
case ST_IS_HIT_NONE:
break;
case ST_IS_HIT_BBOX:
if ( st_IsHitBBOX(objnr, x, y) != 0 )
{
st_Destroy(objnr);
return 1;
}
break;
case ST_IS_HIT_WALL:
if ( st_IsHitBBOX(objnr, x, y) != 0 )
{
o->x0++;
if ( o->x0 < o->x1 )
{
st_NewTrashDust(x, y, ST_OT_DUST_NXPY);
st_NewTrashDust(x, y, ST_OT_DUST_NXNY);
}
else
{
st_Destroy(objnr);
st_NewTrashDust(x, y, ST_OT_DUST_NXPY);
st_NewTrashDust(x, y, ST_OT_DUST_NXNY);
st_NewTrashDust(x, y, ST_OT_DUST_NY);
st_NewTrashDust(x, y, ST_OT_DUST_PY);
}
return 1;
}
break;
}
return 0;
}
/* update all fire counters */
uint8_t st_fire_player = 0;
uint8_t st_fire_period = 51;
uint8_t st_manual_fire_delay = 20;
uint8_t st_is_fire_last_value = 0;
/*
is_auto_fire == 1
is_fire will be ignored, autofire enabled
is_auto_fire == 0
a transition from 1 to 0 on the is_fire variable will issue a missle
*/
void st_FireStep(uint8_t is_auto_fire, uint8_t is_fire)
{
if ( is_auto_fire != 0 )
{
st_fire_player++;
if ( st_fire_player >= st_fire_period )
st_fire_player = 0;
}
else
{
if ( st_fire_player < st_manual_fire_delay )
{
st_fire_player++;
}
else
{
if ( st_is_fire_last_value == 0 )
if ( is_fire != 0 )
st_fire_player = 0;
}
st_is_fire_last_value = is_fire;
}
}
void st_Fire(uint8_t objnr)
{
st_obj *o = st_GetObj(objnr);
uint8_t x;
uint8_t y;
switch(u8x8_pgm_read(&(st_object_types[o->ot].fire_fn)))
{
case ST_FIRE_NONE:
break;
case ST_FIRE_PLAYER1:
if ( st_fire_player == 0 )
{
/* create missle at st_px_x and st_px_y */
x = st_CalcXY(o);
y = st_px_y;
st_NewPlayerMissle(x , y );
}
break;
case ST_FIRE_PLAYER2:
if ( st_fire_player == 0 )
{
/* create missle at st_px_x and st_px_y */
x = st_CalcXY(o);
y = st_px_y;
st_NewPlayerMissle(x , y );
st_NewPlayerMissle(x , y+4 );
}
break;
case ST_FIRE_PLAYER3:
if ( st_fire_player == 0 )
{
/* create missle at st_px_x and st_px_y */
x = st_CalcXY(o);
y = st_px_y;
st_NewPlayerMissle(x , y );
st_NewPlayerMissle(x , y+4 );
st_NewPlayerMissle(x , y-4 );
}
break;
}
}
/*================================================================*/
/* object init functions */
/*================================================================*/
/*
x,y are pixel coordinats within the play arey
*/
void st_NewGadget(uint8_t x, uint8_t y)
{
st_obj *o;
int8_t objnr = st_NewObj();
if ( objnr < 0 )
return;
o = st_GetObj(objnr);
st_SetXY(o, x, y);
o->ot = ST_OT_GADGET;
o->tmp = 8;
//o->x = (x)<<ST_FP;
//o->y = (y)<<ST_FP;
o->x0 = -3;
o->x1 = 1;
o->y0 = -2;
o->y1 = 2;
}
/*
x,y are pixel coordinats within the play arey
dir: direction
0: random
!= 0 --> assigned
*/
void st_InitTrash(uint8_t x, uint8_t y, int8_t dir)
{
st_obj *o;
int8_t objnr = st_NewObj();
if ( objnr < 0 )
return;
o = st_GetObj(objnr);
if ( (st_rnd() & 1) == 0 )
o->ot = ST_OT_TRASH1;
else
o->ot = ST_OT_TRASH2;
if ( dir == 0 )
{
o->tmp = 0;
if ( st_rnd() & 1 )
{
if ( st_rnd() & 1 )
o->tmp++;
else
o->tmp--;
}
}
else
{
o->tmp = dir;
}
st_SetXY(o, x, y);
//o->x = (x)<<ST_FP;
...
This file has been truncated, please download it to see its full contents.
Comments