diff --git a/core.h b/core.h new file mode 100644 index 0000000..2c847e7 --- /dev/null +++ b/core.h @@ -0,0 +1,344 @@ +int file_exists(char* filename) +{ + struct stat statbuf; + if(stat(filename, &statbuf) < 0) + { + if(errno == ENOENT) + return 0; + else + return 1; + } + return 1; +} + + +// core definitions + +CORE::CORE() +{ + rockets = new list(15); + bombs = new list(20); + nukes = new list(5); +} + +CORE::~CORE() +{ + delete this->ground; + delete this->turret; + delete this->gun; + delete this->sky; + delete this->crosshair; + delete this->rocketTrailPiece; + delete this->bombTrailPiece; + delete this->nukeTrailPiece; + + delete this->rockets; + delete this->bombs; + delete this->nukes; +} + +int CORE::load_data() +{ + this->init(); + + // load font + fnt = new hgeFont("data/font.fnt"); + fnt->SetColor(0xFFFFFFFF); + + // create sky + sky = new hgeSprite(0, 0, 0, 800, 600); + sky->SetBlendMode(BLEND_COLORADD | BLEND_ALPHABLEND); + + // create textures + txRocket = hge->Texture_Load("data/rocket.png"); + txBomb = hge->Texture_Load("data/bomb.png"); + txNuke = hge->Texture_Load("data/nuke.png"); + + // create crosshair + txCrosshair = hge->Texture_Load("data/crosshair.png"); + crosshair = new hgeSprite(txCrosshair, 0, 0, 16, 16); + crosshair->SetHotSpot(8, 8); + + // create ground + txGround = hge->Texture_Load("data/ground.png"); + ground = new hgeSprite(txGround, 0, 0, 800, 100); + + // create turret + txTurret = hge->Texture_Load("data/turret.png"); + turret = new hgeSprite(txTurret, 0, 0, 128, 128); + + // create gun + txGun = hge->Texture_Load("data/gun.png"); + gun = new hgeSprite(txGun, 0, 0, 72, 72); + gun->SetHotSpot(36, 56); + this->turretAngle = 0; + + // sign + txSign = hge->Texture_Load("data/sign.png"); + sign = new hgeSprite(txSign, 0, 0, 64, 128); + sign->SetHotSpot(32, 64); + + // create particle systems + txRocketTrail = hge->Texture_Load("data/rockettrail.png"); + rocketTrailPiece = new hgeSprite(txRocketTrail, 0, 0, 24, 24); + rocketTrailPiece->SetHotSpot(12, 12); + rocketTrailPiece->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_ZWRITE); + + txBombTrail = hge->Texture_Load("data/bombtrail.png"); + bombTrailPiece = new hgeSprite(txBombTrail, 0, 0, 32, 32); + bombTrailPiece->SetHotSpot(16, 16); + bombTrailPiece->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_ZWRITE); + + txNukeTrail = hge->Texture_Load("data/nuketrail.png"); + nukeTrailPiece = new hgeSprite(txNukeTrail, 0, 0, 32, 32); + nukeTrailPiece->SetHotSpot(16, 16); + nukeTrailPiece->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_ZWRITE); + + txExplosion = hge->Texture_Load("data/explosion.png"); + explosionPiece = new hgeSprite(txExplosion, 0, 0, 48, 48); + explosionPiece->SetHotSpot(24, 24); + explosionPiece->SetBlendMode(BLEND_COLORMUL | BLEND_ALPHAADD | BLEND_ZWRITE); + + // now make sound! + music = hge->Music_Load("data/bg.mod"); + if(music) channel = hge->Music_Play(music, true); + hge->Channel_SetVolume(channel, 40); + + if(txRocket && txBomb && txCrosshair && txGround && txTurret && txSign && txGun && txRocketTrail && txBombTrail && txExplosion && txNuke && txNukeTrail && music && channel) return 1; + return 0; +} + +void CORE::init() +{ + // values + hge->Random_Seed(0); + this->bombInterval = this->bombTimer = this->bombSpeedup = 4; + this->nukeTimer = 30; + score = fired = hit = 0; + textalpha = 0xFF; + + alive = true; + pause = false; + + // sky & stars + colors[0] = 0; + colors[1] = 16; + colors[2] = 16; + colors[3] = 0; + colors[4] = 21; + colors[5] = 80; + + starcolor = 0; + for(int idx=0; idx<100; idx++) + { + stars[idx].x = hge->Random_Int(0, 800); + stars[idx].y = hge->Random_Int(0, 600); + } + + // empty lists + this->rockets->empty(); + this->bombs->empty(); + this->nukes->empty(); +} + +void CORE::rotate_turret() +{ + if(this->mouseY < 400) + this->turretAngle = atan((this->mouseX-398)/(420-this->mouseY)); + else if(this->mouseX > 398) + this->turretAngle = 3.14/2; + else + this->turretAngle = 3.14*3/2; +} + +void CORE::fire_rocket() +{ + if(this->rockets->length == 15) return; + + // create and set rocket up + rocket *r = new rocket(398 + sin(this->turretAngle)*50, 420 - cos(this->turretAngle)*50, this->turretAngle); + + // add rocket to the list + this->rockets->add(r); +} + +void CORE::drop_bomb() +{ + // create and set bomb up + float x = hge->Random_Int(20, 780); + bomb *b = new bomb(x, -32, 3.14 + atan((hge->Random_Int(200, 600)-x)/(-532))); + + // hard mode ? + if(hge->Timer_GetTime() > 40 && hge->Random_Int(0, 100) > 50) + { + b->curved = true; + b->curve_dir = (hge->Random_Int(0, 100) > 50 ? -1 : 1); + } + + // add bomb to list + this->bombs->add(b); +} + +void CORE::drop_nuke() +{ + // create and set nuke up + float x = hge->Random_Int(20, 780); + nuke *n = new nuke(x, -32, 3.14 + atan((hge->Random_Int(200, 600)-x)/(-532))); + + // add bomb to list + this->nukes->add(n); +} + +void CORE::explode_bombs() +{ + rocket *curr = this->rockets->first; + for(int idx=0; idxrockets->length; idx++) + { + bomb *currb = this->bombs->first; + for(int idx2=0; idx2bombs->length; idx2++) + { + if(curr->collides(currb) && curr->alive) + { + curr->explode(); + currb->explode(); + this->score += (100-currb->y/5); + } + + if(currb->x < -10 || currb->x > 810) currb->explode(); + currb = (bomb *)currb->next; + } + + nuke *currn = this->nukes->first; + for(idx2=0; idx2nukes->length; idx2++) + { + if(curr->collides(currn) && curr->alive) + { + curr->explode(); + currn->explode(); + this->score += (150-currn->y/7); + } + currn = (nuke *)currn->next; + } + + curr = (rocket *)curr->next; + } +} + +void CORE::repaint_sky() +{ + for(int idx=0; idx<6; idx++) + { + if(colors[idx]<0) colors[idx] = 0; + if(colors[idx]>255) colors[idx] = 255; + } + + long col1 = ARGB(0xFF, ((char)colors[0]), ((char)colors[1]), ((char)colors[2])); + long col2 = ARGB(0xFF, ((char)colors[3]), ((char)colors[4]), ((char)colors[5])); + + sky->SetColor(col1, 0); + sky->SetColor(col1, 1); + sky->SetColor(col2, 2); + sky->SetColor(col2, 3); +} + +bool CORE::collect_garbage() +{ + // rockets + rocket *tmp, *curr = this->rockets->first; + for(int idx=0; idxrockets->length; idx++) + { + if(curr->dead_time == 1) + { + this->fired++; + CloseHandle(curr->thread); + this->rockets->del(curr); + tmp = (rocket *)curr->next; + delete curr->body; + delete curr->trail; + delete curr; + curr = tmp; + } + } + + // bombs + bomb *tmpb, *currb = this->bombs->first; + for(idx=0; idxbombs->length; idx++) + { + if(currb->dead_time == 1) + { + CloseHandle(currb->thread); + + if(currb->fatal) + { + alive = false; + return true; + } + + this->hit++; + this->bombs->del(currb); + tmpb = (bomb *)currb->next; + delete currb->body; + delete currb->trail; + delete currb->explosion; + delete currb; + currb = tmpb; + } + } + + // nukes + nuke *tmpn, *currn = this->nukes->first; + for(idx=0; idxnukes->length; idx++) + { + if(currn->dead_time == 1) + { + CloseHandle(currn->thread); + + if(currn->fatal) + { + alive = false; + return true; + } + + this->hit++; + this->nukes->del(currn); + tmpn = (nuke *)currn->next; + delete currn->body; + delete currn->trail; + delete currn->explosion; + delete currn; + currn = tmpn; + } + } + + return false; +} + + +void CORE::debug_render() +{ + fnt->printf(5, 20, HGETEXT_LEFT, "Threads working: %i", bombs->length + rockets->length + nukes->length); + int y=32; + dynamic_spr *curr = rockets->first; + for(int idx=0; idxlength; idx++) + { + fnt->printf(5, y, HGETEXT_LEFT, "[addr %p, handle %i] rocket", curr, curr->thread); + curr = curr->next; + y+=12; + } + + curr = bombs->first; + for(idx=0; idxlength; idx++) + { + fnt->printf(5, y, HGETEXT_LEFT, "[addr %p, handle %i] bomb", curr, curr->thread); + curr = curr->next; + y+=12; + } + + curr = nukes->first; + for(idx=0; idxlength; idx++) + { + fnt->printf(5, y, HGETEXT_LEFT, "[addr %p, handle %i] nuke", curr, curr->thread); + curr = curr->next; + y+=12; + } +} \ No newline at end of file diff --git a/data/bg.mod b/data/bg.mod new file mode 100644 index 0000000..7edc053 Binary files /dev/null and b/data/bg.mod differ diff --git a/data/bomb.png b/data/bomb.png new file mode 100644 index 0000000..4bb1e82 Binary files /dev/null and b/data/bomb.png differ diff --git a/data/bombtrail.png b/data/bombtrail.png new file mode 100644 index 0000000..908649d Binary files /dev/null and b/data/bombtrail.png differ diff --git a/data/bombtrail.psi b/data/bombtrail.psi new file mode 100644 index 0000000..7e60d31 Binary files /dev/null and b/data/bombtrail.psi differ diff --git a/data/crosshair.png b/data/crosshair.png new file mode 100644 index 0000000..304d40d Binary files /dev/null and b/data/crosshair.png differ diff --git a/data/explosion.png b/data/explosion.png new file mode 100644 index 0000000..f4a85b5 Binary files /dev/null and b/data/explosion.png differ diff --git a/data/explosion.psi b/data/explosion.psi new file mode 100644 index 0000000..ee72b89 Binary files /dev/null and b/data/explosion.psi differ diff --git a/data/font.fnt b/data/font.fnt new file mode 100644 index 0000000..e7e8ac6 --- /dev/null +++ b/data/font.fnt @@ -0,0 +1,165 @@ +[HGEFONT] + +Bitmap=font.png + +Char=" ",0,0,3,12,0,0 +Char="!",3,0,3,12,0,0 +Char=""",6,0,5,12,0,0 +Char="#",11,0,7,12,0,0 +Char="$",18,0,6,12,0,0 +Char="%",24,0,8,12,0,0 +Char="&",32,0,6,12,0,0 +Char="'",38,0,2,12,0,0 +Char="(",40,0,3,12,0,0 +Char=")",43,0,3,12,0,0 +Char="*",46,0,4,12,0,0 +Char="+",50,0,6,12,0,0 +Char=",",56,0,3,12,0,0 +Char="-",59,0,3,12,0,0 +Char=".",62,0,3,12,0,0 +Char="/",65,0,5,12,0,0 +Char="0",70,0,6,12,0,0 +Char="1",76,0,6,12,0,0 +Char="2",82,0,6,12,0,0 +Char="3",88,0,6,12,0,0 +Char="4",94,0,6,12,0,0 +Char="5",100,0,6,12,0,0 +Char="6",106,0,6,12,0,0 +Char="7",112,0,6,12,0,0 +Char="8",118,0,6,12,0,0 +Char="9",0,12,6,12,0,0 +Char=":",6,12,3,12,0,0 +Char=";",9,12,3,12,0,0 +Char="<",12,12,6,12,0,0 +Char="=",18,12,6,12,0,0 +Char=">",24,12,6,12,0,0 +Char="?",30,12,6,12,0,0 +Char="@",36,12,11,12,0,0 +Char="A",47,12,7,12,0,0 +Char="B",54,12,7,12,0,0 +Char="C",61,12,7,12,0,0 +Char="D",68,12,8,12,0,0 +Char="E",76,12,7,12,0,0 +Char="F",83,12,6,12,0,0 +Char="G",89,12,8,12,0,0 +Char="H",97,12,8,12,0,0 +Char="I",105,12,3,12,0,0 +Char="J",108,12,5,12,0,0 +Char="K",113,12,7,12,0,0 +Char="L",120,12,6,12,0,0 +Char="M",0,24,9,12,0,0 +Char="N",9,24,8,12,0,0 +Char="O",17,24,8,12,0,0 +Char="P",25,24,7,12,0,0 +Char="Q",32,24,8,12,0,0 +Char="R",40,24,8,12,0,0 +Char="S",48,24,7,12,0,0 +Char="T",55,24,7,12,0,0 +Char="U",62,24,8,12,0,0 +Char="V",70,24,7,12,0,0 +Char="W",77,24,11,12,0,0 +Char="X",88,24,7,12,0,0 +Char="Y",95,24,7,12,0,0 +Char="Z",102,24,7,12,0,0 +Char="[",109,24,3,12,0,0 +Char="\",112,24,5,12,0,0 +Char="]",117,24,3,12,0,0 +Char="^",120,24,6,12,0,0 +Char="_",0,36,6,12,0,0 +Char="`",6,36,3,12,0,0 +Char="a",9,36,6,12,0,0 +Char="b",15,36,6,12,0,0 +Char="c",21,36,6,12,0,0 +Char="d",27,36,6,12,0,0 +Char="e",33,36,6,12,0,0 +Char="f",39,36,3,12,0,0 +Char="g",42,36,6,12,0,0 +Char="h",48,36,6,12,0,0 +Char="i",54,36,2,12,0,0 +Char="j",56,36,2,12,0,0 +Char="k",58,36,6,12,0,0 +Char="l",64,36,2,12,0,0 +Char="m",66,36,8,12,0,0 +Char="n",74,36,6,12,0,0 +Char="o",80,36,6,12,0,0 +Char="p",86,36,6,12,0,0 +Char="q",92,36,6,12,0,0 +Char="r",98,36,3,12,0,0 +Char="s",101,36,5,12,0,0 +Char="t",106,36,3,12,0,0 +Char="u",109,36,6,12,0,0 +Char="v",115,36,6,12,0,0 +Char="w",0,48,8,12,0,0 +Char="x",8,48,5,12,0,0 +Char="y",13,48,5,12,0,0 +Char="z",18,48,5,12,0,0 +Char="{",23,48,4,12,0,0 +Char="|",27,48,2,12,0,0 +Char="}",29,48,4,12,0,0 +Char="~",33,48,7,12,0,0 +Char=7F,40,48,88,12,0,0 +Char=80,0,60,128,12 +Char=C0,0,72,7,12 +Char=C1,7,72,7,12 +Char=C2,14,72,7,12 +Char=C3,21,72,6,12 +Char=C4,27,72,9,12 +Char=C5,36,72,7,12 +Char=C6,43,72,11,12 +Char=C7,54,72,7,12 +Char=C8,61,72,8,12 +Char=C9,69,72,8,12 +Char=CA,77,72,7,12 +Char=CB,84,72,8,12 +Char=CC,92,72,9,12 +Char=CD,101,72,8,12 +Char=CE,109,72,8,12 +Char=CF,117,72,8,12 +Char=D0,0,84,7,12 +Char=D1,7,84,7,12 +Char=D2,14,84,7,12 +Char=D3,21,84,8,12 +Char=D4,29,84,11,12 +Char=D5,40,84,7,12 +Char=D6,47,84,8,12 +Char=D7,55,84,8,12 +Char=D8,63,84,9,12 +Char=D9,72,84,10,12 +Char=DA,82,84,8,12 +Char=DB,90,84,10,12 +Char=DC,100,84,8,12 +Char=DD,108,84,7,12 +Char=DE,115,84,9,12 +Char=DF,0,96,8,12 +Char=E0,8,96,6,12 +Char=E1,14,96,6,12 +Char=E2,20,96,6,12 +Char=E3,26,96,5,12 +Char=E4,31,96,6,12 +Char=E5,37,96,6,12 +Char=E6,43,96,8,12 +Char=E7,51,96,6,12 +Char=E8,57,96,6,12 +Char=E9,63,96,6,12 +Char=EA,69,96,6,12 +Char=EB,75,96,6,12 +Char=EC,81,96,8,12 +Char=ED,89,96,6,12 +Char=EE,95,96,6,12 +Char=EF,101,96,6,12 +Char=F0,107,96,6,12 +Char=F1,113,96,6,12 +Char=F2,119,96,5,12 +Char=F3,0,108,5,12 +Char=F4,5,108,8,12 +Char=F5,13,108,5,12 +Char=F6,18,108,6,12 +Char=F7,24,108,5,12 +Char=F8,29,108,8,12 +Char=F9,37,108,9,12 +Char=FA,46,108,7,12 +Char=FB,53,108,8,12 +Char=FC,61,108,6,12 +Char=FD,67,108,6,12 +Char=FE,73,108,8,12 +Char=FF,81,108,6,12 diff --git a/data/font.png b/data/font.png new file mode 100644 index 0000000..fcfd9d1 Binary files /dev/null and b/data/font.png differ diff --git a/data/ground.png b/data/ground.png new file mode 100644 index 0000000..c099198 Binary files /dev/null and b/data/ground.png differ diff --git a/data/gun.png b/data/gun.png new file mode 100644 index 0000000..855232b Binary files /dev/null and b/data/gun.png differ diff --git a/data/nuke.png b/data/nuke.png new file mode 100644 index 0000000..cdbe95b Binary files /dev/null and b/data/nuke.png differ diff --git a/data/nuketrail.png b/data/nuketrail.png new file mode 100644 index 0000000..840d79e Binary files /dev/null and b/data/nuketrail.png differ diff --git a/data/rocket.png b/data/rocket.png new file mode 100644 index 0000000..552e250 Binary files /dev/null and b/data/rocket.png differ diff --git a/data/rockettrail.png b/data/rockettrail.png new file mode 100644 index 0000000..2832a20 Binary files /dev/null and b/data/rockettrail.png differ diff --git a/data/rockettrail.psi b/data/rockettrail.psi new file mode 100644 index 0000000..cd09726 Binary files /dev/null and b/data/rockettrail.psi differ diff --git a/data/sign.png b/data/sign.png new file mode 100644 index 0000000..7dbb73f Binary files /dev/null and b/data/sign.png differ diff --git a/data/turret.png b/data/turret.png new file mode 100644 index 0000000..f2e1114 Binary files /dev/null and b/data/turret.png differ diff --git a/gfx/bomb.fla b/gfx/bomb.fla new file mode 100644 index 0000000..7bfdf81 Binary files /dev/null and b/gfx/bomb.fla differ diff --git a/gfx/bombtrail.fla b/gfx/bombtrail.fla new file mode 100644 index 0000000..fa252be Binary files /dev/null and b/gfx/bombtrail.fla differ diff --git a/gfx/explosion.fla b/gfx/explosion.fla new file mode 100644 index 0000000..579acdf Binary files /dev/null and b/gfx/explosion.fla differ diff --git a/gfx/ground.fla b/gfx/ground.fla new file mode 100644 index 0000000..add3172 Binary files /dev/null and b/gfx/ground.fla differ diff --git a/gfx/gun.fla b/gfx/gun.fla new file mode 100644 index 0000000..90129b5 Binary files /dev/null and b/gfx/gun.fla differ diff --git a/gfx/nuke.fla b/gfx/nuke.fla new file mode 100644 index 0000000..21c5746 Binary files /dev/null and b/gfx/nuke.fla differ diff --git a/gfx/nuketrail.fla b/gfx/nuketrail.fla new file mode 100644 index 0000000..442cd38 Binary files /dev/null and b/gfx/nuketrail.fla differ diff --git a/gfx/rocket.fla b/gfx/rocket.fla new file mode 100644 index 0000000..7c493ee Binary files /dev/null and b/gfx/rocket.fla differ diff --git a/gfx/rockettrail.fla b/gfx/rockettrail.fla new file mode 100644 index 0000000..833cc33 Binary files /dev/null and b/gfx/rockettrail.fla differ diff --git a/gfx/turret.fla b/gfx/turret.fla new file mode 100644 index 0000000..8d3664c Binary files /dev/null and b/gfx/turret.fla differ diff --git a/invasion.cpp b/invasion.cpp new file mode 100644 index 0000000..f1189d7 --- /dev/null +++ b/invasion.cpp @@ -0,0 +1,228 @@ +#include +#include +#include + +#include +#include +#include +#include + +HGE *hge = 0; + +#include "predefine.h" +#include "list.h" +#include "core.h" + +CORE *core = 0; + +#include "sprites.h" +#include "threads.h" + +bool FrameFuncLost() +{ + if(hge->Input_KeyDown(HGEK_ESCAPE)) return true; + + if(hge->Input_KeyDown(HGEK_ENTER) || hge->Input_KeyDown(HGEK_LBUTTON)) + { + core->init(); + core->fnt->SetColor(0xFFFFFFFF); + hge->System_SetState(HGE_FRAMEFUNC, FrameFunc); + hge->System_SetState(HGE_RENDERFUNC, RenderFunc); + } + + return false; +} + +bool RenderFuncLost() +{ + hge->Gfx_BeginScene(); + core->sky->Render(0, 0); + core->fnt->printf(400, 250, HGETEXT_CENTER, "You have lost!\n\nYour score was %i points.\n\nBetter luck next time!", core->score); + hge->Gfx_EndScene(); + return false; +} + +bool FrameFunc() +{ + // quit if Escape pressed + if(hge->Input_KeyDown(HGEK_ESCAPE)) return true; + + if(hge->Input_KeyDown(HGEK_P)) + core->pause = core->pause ? false : true; + + if(hge->Input_KeyDown(HGEK_S)) + if(hge->Channel_IsPlaying(core->channel)) + hge->Channel_Pause(core->channel); + else + hge->Channel_Resume(core->channel); + + if(!core->pause) + { + // rotate turret + hge->Input_GetMousePos(&(core->mouseX), &(core->mouseY)); + core->rotate_turret(); + + // fire rocket? + if(hge->Input_KeyDown(HGEK_LBUTTON)) + core->fire_rocket(); + + // create bombs + core->bombTimer -= hge->Timer_GetDelta(); + if(core->bombTimer <= 0) + { + core->drop_bomb(); + core->bombTimer = core->bombInterval; + } + + // create nukes + core->nukeTimer -= hge->Timer_GetDelta(); + if(core->nukeTimer <= 0) + { + core->drop_nuke(); + core->nukeTimer = 15; + } + + // speed up bombs + core->bombSpeedup -= hge->Timer_GetDelta(); + if(core->bombSpeedup <=0) + { + core->bombSpeedup = 4; + if(core->bombInterval > 0.8) core->bombInterval -= 0.075; + } + + core->explode_bombs(); + + if(hge->Timer_GetTime() > 20 && (char)(core->starcolor) < 0x70) core->starcolor+=0.1; + + if(core->collect_garbage()) + { + // convert sky + core->sky->SetColor(0x0FFFFFFF, 0); + core->sky->SetColor(0x0FFFFFFF, 1); + core->sky->SetColor(0x15FFFFFF, 2); + core->sky->SetColor(0x15FFFFFF, 3); + + core->fnt->SetColor(0xFF000000); + + hge->System_SetState(HGE_FRAMEFUNC, FrameFuncLost); + hge->System_SetState(HGE_RENDERFUNC, RenderFuncLost); + } + + // debug info + if(hge->Input_KeyDown(HGEK_CTRL)) + core->debug = (core->debug ? false : true); + } + + return false; +} + +bool RenderFunc() +{ + hge->Gfx_BeginScene(); + + if(!core->pause) + { + // render BG + core->repaint_sky(); + core->sky->Render(0, 0); + for(int idx=0; idx<100; idx++) + { + core->stars[idx].y+=0.1; + core->stars[idx].x+=hge->Random_Float(-0.2, 0.2); + if(core->stars[idx].y > 530) + { + core->stars[idx].x = hge->Random_Int(0, 800); + core->stars[idx].y = -10; + } + hge->Gfx_RenderLine(core->stars[idx].x, core->stars[idx].y, core->stars[idx].x+1, core->stars[idx].y, ARGB((char)core->starcolor, 0xFF, 0xFF, 0xFF)); + } + + // render objects + core->rockets->render(); + core->bombs->render(); + core->nukes->render(); + + // render gun + core->gun->RenderEx(398, 420, core->turretAngle, 1); + + // signs + core->sign->RenderEx(64, 470, -0.1, 0.7); + core->sign->RenderEx(264, 485, 0.1, 0.3); + core->sign->RenderEx(736, 460, 0.25, 0.8); + + // render FG + core->turret->Render(336, 400); + core->ground->Render(0, 500); + + // crosshair + core->crosshair->Render(core->mouseX, core->mouseY); + + if(hge->Timer_GetTime() < 3) + { + core->fnt->printf(400, 250, HGETEXT_CENTER, "Destroy all the bombs before they hit the ground!"); + } + else if(hge->Timer_GetTime() < 4) + { + if(hge->Timer_GetTime() > 3.5) + { + core->textalpha-=5; + core->fnt->SetColor(ARGB((char)core->textalpha, 0xFF, 0xFF, 0xFF)); + } + core->fnt->printf(400, 250, HGETEXT_CENTER, "HERE THEY COME!"); + } + + if(hge->Timer_GetTime() < 5) core->fnt->SetColor(0xE0FFFFFF); + core->fnt->printf(5, 5, HGETEXT_LEFT, "Score: %i points", core->score); + + if(hge->Input_GetKeyState(HGEK_C)) core->fnt->printf(795, 5, HGETEXT_RIGHT, "Made by Imp, 2008\nGreetings to natasha,\nbr, blew, demix, zabava\n\nÏÛÙÜ ÏÛÙÜ!!!!1\n\nÀ òêà÷ íå íÿ :]"); + if(core->debug) core->debug_render(); + } + else + { + core->fnt->printf(400, 300, HGETEXT_CENTER, "Paused"); + } + + hge->Gfx_EndScene(); + return false; +} + +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + HANDLE exists = CreateMutex(NULL, false, TEXT("invasion1337")); + if(GetLastError() == ERROR_ALREADY_EXISTS) + { + MessageBox(NULL, "Don't run me twice!", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL); + return 0; + } + + CreateMutex(NULL, false, TEXT("invasion1337")); + hge = hgeCreate(HGE_VERSION); + core = new CORE(); + + hge->System_SetState(HGE_FRAMEFUNC, FrameFunc); + hge->System_SetState(HGE_RENDERFUNC, RenderFunc); + hge->System_SetState(HGE_USESOUND, true); + + hge->System_SetState(HGE_SHOWSPLASH, false); + hge->System_SetState(HGE_FPS, 100); + hge->System_SetState(HGE_WINDOWED, true); + hge->System_SetState(HGE_SCREENWIDTH, 800); + hge->System_SetState(HGE_SCREENHEIGHT, 600); + hge->System_SetState(HGE_SCREENBPP, 32); + hge->System_SetState(HGE_TITLE, "Invasion"); + + if(hge->System_Initiate()) + { + if(core->load_data()) + hge->System_Start(); + else + MessageBox(NULL, "Game data files are missing!", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL); + } + else + MessageBox(NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL); + + hge->System_Shutdown(); + hge->Release(); + + return 0; +} diff --git a/invasion.dsp b/invasion.dsp new file mode 100644 index 0000000..4e8662a --- /dev/null +++ b/invasion.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="invasion" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=invasion - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "invasion.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "invasion.mak" CFG="invasion - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "invasion - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "invasion - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "invasion - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib hge.lib hgehelp.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "invasion - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib hge.lib hgehelp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "invasion - Win32 Release" +# Name "invasion - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\invasion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\core.h +# End Source File +# Begin Source File + +SOURCE=.\list.h +# End Source File +# Begin Source File + +SOURCE=.\predefine.h +# End Source File +# Begin Source File + +SOURCE=.\sprites.h +# End Source File +# Begin Source File + +SOURCE=.\threads.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/invasion.dsw b/invasion.dsw new file mode 100644 index 0000000..48e70fc --- /dev/null +++ b/invasion.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "invasion"=.\invasion.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/list.h b/list.h new file mode 100644 index 0000000..03df3d1 --- /dev/null +++ b/list.h @@ -0,0 +1,100 @@ +// dynamic list template + +template +list::list(int nmax) +{ + this->first = this->last = NULL; + this->length = 0; + this->max = nmax; +} + +template +list::~list() +{ + while(this->length > 0) + { + Type *next = (Type *)this->first->next; + delete this->first; + this->first = next; + this->length--; + } +} + +template +void list::add(Type *obj) +{ + //if(this->length == this->max) return; + + if(this->length == 0) + { + this->first = this->last = obj; + } + else + { + this->last->next = obj; + obj->prev = this->last; + this->last = obj; + } + this->length++; +} + +template +void list::del(Type *obj) +{ + if(obj == this->first) + { + this->first = (Type *)this->first->next; + } + else if(obj == this->last) + { + this->last = (Type *)this->last->prev; + } + else + { + obj->prev->next = (Type *)obj->next; + obj->next->prev = (Type *)obj->prev; + } + this->length--; +} + +template +Type * list::get(int id) +{ + if(id > this->length-1) return NULL; + Type *curr = this->first; + for(int idx=0; idxnext; + } + return curr; +} + +template +void list::empty() +{ + Type *tmp, *curr = this->first; + for(int idx=0; idxlength; idx++) + { + tmp = (Type *)curr->next; + CloseHandle(curr->thread); + delete curr->trail; + delete curr->body; + if(curr->explosion) delete curr->explosion; + delete curr; + curr = tmp; + } + this->length = 0; +} + +template +void list::render() +{ + Type *curr = this->first; + for(int idx=0; idxlength; idx++) + { + curr->trail->Render(); + if(curr->alive) curr->body->RenderEx(curr->x, curr->y, curr->angle, 1); + if(curr->explosion) curr->explosion->Render(); + curr = (Type *)curr->next; + } +} diff --git a/predefine.h b/predefine.h new file mode 100644 index 0000000..cea09d3 --- /dev/null +++ b/predefine.h @@ -0,0 +1,174 @@ +class CORE; +class dynamic_spr; +class rocket; +class bomb; +class nuke; + +DWORD WINAPI UpdateRocket(LPVOID rpointer); +DWORD WINAPI UpdateBomb(LPVOID bpointer); + +bool FrameFunc(); +bool RenderFunc(); +bool FrameFuncLost(); +bool RenderFuncLost(); + +// common active object class + +class dynamic_spr +{ + public: + hgeSprite *body; + hgeParticleSystem *trail, *explosion; + float x, y; + float angle, speed; + float dead_time; + dynamic_spr *next, *prev; + bool alive; + + HANDLE thread; + + dynamic_spr(float nx, float ny, float nangle) + { + body = NULL; + trail = explosion = NULL; + next = prev = NULL; + x = nx; + y = ny; + angle = nangle; + speed = 0; + thread = 0; + alive = false; + } + + int collides(dynamic_spr *obj) + { + if(abs(this->x - obj->x) < 16 && abs(this->y - obj->y) < 16 && obj->alive) return true; + return false; + } +}; + + + + +// rocket class + +class rocket: public dynamic_spr +{ + public: + + rocket(float x, float y, float angle); + + void explode(); +}; + + + + +// bomb class + +class bomb: public dynamic_spr +{ + public: + bool fatal, curved; + float angle_offset; + int curve_dir; + + bomb(float x, float y, float angle); + + void explode(); +}; + + + +// nuke class + +class nuke: public dynamic_spr +{ + public: + bool fatal, curved; + + nuke(float x, float y, float angle); + + void explode(); +}; + + + + +template +class list +{ + public: + Type *first, *last; + int length, max; + + list(int nmax); + ~list(); + + void add(Type *obj); + void del(Type *obj); + Type * get(int id); + void empty(); + + void render(); +}; + + +// core class + +class CORE +{ + public: + HMUSIC music; + + HCHANNEL channel; + + HTEXTURE + txGround, txSky, + txTurret, txGun, + txRocket, txRocketTrail, + txBomb, txBombTrail, + txNuke, txNukeTrail, + txExplosion, + txCrosshair, + txSign; + + hgeSprite + *ground, *sky, + *turret, *gun, + *crosshair, + *rocketTrailPiece, *bombTrailPiece, *explosionPiece, *nukeTrailPiece, + *sign; + + hgeFont *fnt; + + list *rockets; + list *bombs; + list *nukes; + + struct { float x, y; } stars[100]; + + float turretAngle, mouseX, mouseY; + float bombTimer, nukeTimer, bombInterval, bombSpeedup; + + float colors[6], starcolor, textalpha; + + long score, fired, hit; + bool alive, pause, debug; + + CORE(); + ~CORE(); + + int load_data(); + void init(); + void rotate_turret(); + void fire_rocket(); + void drop_bomb(); + void drop_nuke(); + void explode_bombs(); + void repaint_sky(); + + void debug_render(); + + bool collect_garbage(); +}; \ No newline at end of file diff --git a/sprites.h b/sprites.h new file mode 100644 index 0000000..08a8a59 --- /dev/null +++ b/sprites.h @@ -0,0 +1,106 @@ +// rocket + +rocket::rocket(float x, float y, float angle):dynamic_spr(x, y, angle) +{ + speed = 1; + body = new hgeSprite(core->txRocket, 0, 0, 24, 24); + body->SetHotSpot(12, 12); + alive = true; + + dead_time = 0; + + // create trail + trail = new hgeParticleSystem("data/rockettrail.psi", core->rocketTrailPiece); + trail->FireAt(this->x, this->y); + + // create working thread + this->thread = CreateThread(NULL, 0, UpdateRocket, (LPVOID)this, 0, 0); +} + +void rocket::explode() +{ + this->alive = false; + this->trail->Stop(); +} + + + +// bomb + +bomb::bomb(float x, float y, float angle):dynamic_spr(x, y, angle) +{ + speed = 1; + body = new hgeSprite(core->txBomb, 0, 0, 32, 32); + body->SetHotSpot(16, 16); + + alive = true; + dead_time = 0; + fatal = false; + curved = false; + curve_dir = 0; + angle_offset = 0; + + // create trail + trail = new hgeParticleSystem("data/bombtrail.psi", core->bombTrailPiece); + trail->FireAt(x, y); + + // prepare explosion + explosion = new hgeParticleSystem("data/explosion.psi", core->explosionPiece); + + // create working thread + thread = CreateThread(NULL, 0, UpdateBomb, (LPVOID)this, 0, 0); +} + +void bomb::explode() +{ + this->fatal = false; + this->alive = false; + this->trail->Stop(); + this->explosion->FireAt(this->x, this->y); +} + + + +// nuke + +nuke::nuke(float x, float y, float angle):dynamic_spr(x, y, angle) +{ + speed = 0.7; + body = new hgeSprite(core->txNuke, 0, 0, 48, 48); + body->SetHotSpot(24, 24); + + alive = true; + dead_time = 0; + fatal = false; + curved = false; + + // create trail + trail = new hgeParticleSystem("data/bombtrail.psi", core->nukeTrailPiece); + trail->FireAt(x, y); + + // prepare explosion + explosion = new hgeParticleSystem("data/explosion.psi", core->explosionPiece); + + // create working thread + thread = CreateThread(NULL, 0, UpdateBomb, (LPVOID)this, 0, 0); +} + +void nuke::explode() +{ + bomb *b = new bomb(this->x, this->y, 3.14-hge->Random_Float(0, 0.5)); + b->speed = 0.7; + b->curved = true; + b->curve_dir = (hge->Random_Int(0, 100) > 50 ? -1 : 1); + core->bombs->add(b); + + b = new bomb(this->x, this->y, 3.14+hge->Random_Float(0, 0.5)); + b->speed = 0.7; + b->curved = true; + b->curve_dir = (hge->Random_Int(0, 100) > 50 ? -1 : 1); + core->bombs->add(b); + + this->fatal = false; + this->alive = false; + this->trail->Stop(); + this->explosion->FireAt(this->x, this->y); +} \ No newline at end of file diff --git a/threads.h b/threads.h new file mode 100644 index 0000000..7ebedc0 --- /dev/null +++ b/threads.h @@ -0,0 +1,87 @@ +DWORD WINAPI UpdateRocket(LPVOID rpointer) +{ + rocket *curr = (rocket *) rpointer; + while(curr->dead_time < 0.5 && core->alive) + { + if(!core->pause) + { + if(curr->alive) + { + curr->x += sin(curr->angle)*curr->speed; + curr->y -= cos(curr->angle)*curr->speed; + curr->speed += 0.05; + curr->trail->MoveTo(curr->x-sin(curr->angle)*12, curr->y+cos(curr->angle)*12); + } + + if((curr->x < -30 || curr->x > 830 || curr->y < -30) && curr->alive) + { + curr->alive = false; + curr->trail->Stop(); + } + + if(!curr->alive) + { + curr->dead_time += hge->Timer_GetDelta(); + } + + curr->trail->Update(hge->Timer_GetDelta()); + } + + Sleep(9); + } + curr->dead_time = 1; + return 0; +} + +DWORD WINAPI UpdateBomb(LPVOID bpointer) +{ + bomb *curr = (bomb *)bpointer; + while(curr->dead_time < 0.9 && core->alive) + { + if(!core->pause) + { + if(curr->alive) + { + curr->x += sin(curr->angle)*curr->speed; + curr->y -= cos(curr->angle)*curr->speed; + if(curr->curved) + { + curr->angle += sin(curr->angle_offset)/100*curr->curve_dir; + curr->angle_offset += 0.02; + if(curr->angle_offset > 6.28) curr->angle_offset = 0; + } + + curr->trail->MoveTo(curr->x-sin(curr->angle)*12, curr->y+cos(curr->angle)*12); + } + + if(curr->y > 440) + { + core->colors[0]++; + core->colors[1]--; + core->colors[2]--; + core->colors[3]++; + core->colors[4]--; + core->colors[5]--; + } + + // explode reaching bombs + if(curr->y >= 500 && curr->alive) + { + curr->explode(); + curr->fatal = true; + } + + if(!curr->alive) + { + curr->dead_time += hge->Timer_GetDelta(); + } + + curr->trail->Update(hge->Timer_GetDelta()); + curr->explosion->Update(hge->Timer_GetDelta()); + } + + Sleep(9); + } + curr->dead_time = 1; + return 0; +} \ No newline at end of file