/*=============================================================================================
Project: Chemobase Pixel Physics
Author: Felix Queißner
=============================================================================================*/
#include <acknex.h>
#include <default.c>
#include <mtlView.c>
#define SOLID (1<<0)
#define FLAMMABLE (1<<1)
#define FLUID (1<<2)
var use_brown = 0;
typedef struct
{
var type;
void* eventUp;
void* eventDown;
var blue, green,red;
var flags;
var skill[100];
char* name;
} PART;
PART particleData[240][320];
PART* pData[128];
function particleEvent(var x, var y, PART* part);
#define p(x,y) particleData[x][y]
#define pEventUp(x,y) particleEvent = particleData[x][y].eventUp; particleEvent(x,y,particleData[x][y])
#define pEventDown(x,y) particleEvent = particleData[x][y].eventDown; particleEvent(x,y,particleData[x][y])
function pset(var x,var y, PART* part)
{
p(x,y).type = part.type;
p(x,y).eventUp = part.eventUp;
p(x,y).eventDown = part.eventDown;
p(x,y).blue = part.blue;
p(x,y).green = part.green;
p(x,y).red = part.red;
p(x,y).flags = part.flags;
}
BMAP* bmpOutput = "#240x320x24";
VECTOR area;
VECTOR bounds;
PANEL* panOutput =
{
bmap = bmpOutput;
event = clickPanel;
flags = SHOW | FILTER;
layer = 2;
}
PART partDust;
PART partWater;
PART partBlock;
PART partAcid;
PART partOil;
PART partClone;
PART partVirus;
PART partFire;
PART partEmpty;
PART* partSet;
function clickPanel()
{
if(key_shift)
{
var y = mouse_pos.y - panOutput.pos_y;
y /= panOutput.scale_y;
var px,py;
for(py = bounds.y; py >= y; py--)
{
for(px = 0; px < area.x; px++)
{
if(p(px,py).type == 0 || partSet.type == 0)
{
pset(px,py,partSet);
}
}
}
return;
}
while(mouse_left)
{
var x = mouse_pos.x - panOutput.pos_x;
var y = mouse_pos.y - panOutput.pos_y;
x /= panOutput.scale_x;
y /= panOutput.scale_y;
var px,py;
for(px = maxv(x - 4,0); px < minv(x + 5,area.x); px++)
{
for(py = maxv(y - 4,0); py < minv(y + 5,area.y); py++)
{
if((p(px,py).type == 0 || partSet.type == 0))
{
pset(px,py,partSet);
}
}
}
wait(1);
}
}
function partDust_event(var x, var y, PART* part)
{
if(y == bounds.y)
return;
if(p(x,y + 1).type == 0)
{
pset(x,y + 1,part);
pset(x,y,partEmpty);
}
}
function partFuildBrownMovement(var x, var y, PART* part)
{
var px,py;
for(px = maxv(x - 1,0); px <= minv(x + 1,bounds.x); px++)
{
for(py = maxv(y - 1,0); py <= minv(y + 1,bounds.y); py++)
{
if(p(px,py).flags & FLUID)
{
if(random(100)<10)
{
var pMy = p(x,y).type;
var pYou = p(px,py).type;
pset(x,y,pData[pYou]);
pset(px,py,pData[pMy]);
return;
}
}
}
}
}
function partFluidBase_event(var x, var y, PART* part)
{
if(use_brown)
partFuildBrownMovement(x,y,part);
if(y < bounds.y)
{
if(p(x,y + 1).type == 0)
{
pset(x,y + 1,part);
pset(x,y,partEmpty);
return;
}
if(x > 0)
{
if(p(x - 1,y + 1).type == 0)
{
pset(x - 1,y + 1,part);
pset(x,y,partEmpty);
return;
}
}
if(x < bounds.x)
{
if(p(x + 1,y + 1).type == 0)
{
pset(x + 1,y + 1,part);
pset(x,y,partEmpty);
return;
}
}
}
if(x > 0 && x < bounds.x && y > 0)
{
if(p(x - 1,y - 1).type == 0)
{
if(p(x + 1,y).type == 0)
{
pset(x + 1,y,part);
pset(x,y,partEmpty);
return;
}
}
if(p(x + 1,y - 1).type == 0)
{
if(p(x - 1,y).type == 0)
{
pset(x - 1,y,part);
pset(x,y,partEmpty);
return;
}
}
}
if(random(100) < 50)
{
if(x > 0)
{
if(p(x - 1,y).type == 0)
{
pset(x - 1,y,part);
pset(x,y,partEmpty);
return;
}
}
}
else
{
if(x < bounds.x)
{
if(p(x + 1,y).type == 0)
{
pset(x + 1,y,part);
pset(x,y,partEmpty);
return;
}
}
}
}
function partAcid_event(var x, var y, PART* part)
{
partFluidBase_event(x,y,part);
var px,py;
for(px = maxv(x - 1,0); px <= minv(x + 1,bounds.x); px++)
{
for(py = maxv(y - 1,0); py <= minv(y + 1,bounds.y); py++)
{
if(p(px,py).type == 0)
continue;
if(p(px,py).flags & SOLID)
{
if(random(100) < 5)
{
pset(px,py,partEmpty);
pset(x,y,partEmpty);
return;
}
}
}
}
}
function partVirus_event(var x, var y, PART* part)
{
var px,py;
if(random(100) < 10)
{
for(px = maxv(x - 1,0); px <= minv(x + 1,bounds.x); px++)
{
for(py = maxv(y - 1,0); py <= minv(y + 1,bounds.y); py++)
{
if(random(100)<10)
{
if(p(px,py).type == 0)
pset(px,py,pData[part.type]);
return;
}
}
}
}
}
function partClone_event(var x, var y, PART* part)
{
var px,py;
if(part.skill1 == 0)
{
for(px = maxv(x - 1,0); px <= minv(x + 1,bounds.x); px++)
{
for(py = maxv(y - 1,0); py <= minv(y + 1,bounds.y); py++)
{
if(px == x && py == y)
continue;
if(p(px,py).type == part.type)
{
part.skill1 = p(px,py).skill1;
}
if(p(px,py).type != 0 && p(px,py).type != part.type)
{
part.skill1 = p(px,py).type;
}
}
}
}
else
{
if(random(100) < 10)
{
for(px = maxv(x - 1,0); px <= minv(x + 1,bounds.x); px++)
{
for(py = maxv(y - 1,0); py <= minv(y + 1,bounds.y); py++)
{
if(random(100)<10)
{
if(p(px,py).type == 0)
pset(px,py,pData[part.skill1]);
return;
}
}
}
}
}
}
function partFire_event(var x, var y, PART* part)
{
if(y == 0)
{
pset(x,y,partEmpty);
return;
}
part.green = minv(part.green + 0.5,255);
if(x > 0 && random(100) < 25)
{
if(p(x - 1,y).type == 0)
{
pset(x - 1,y,part);
pset(x,y,partEmpty);
return;
}
}
else
{
if(x < bounds.x && random(100) < 25)
{
if(p(x + 1,y).type == 0)
{
pset(x + 1,y,part);
pset(x,y,partEmpty);
return;
}
}
}
if(p(x,y - 1).type == 0)
{
pset(x,y - 1,part);
pset(x,y,partEmpty);
return;
}
if(x > 0)
{
if(p(x - 1,y).flags & FLAMMABLE)
{
pset(x - 1,y,partFire);
return;
}
}
if(x < bounds.x)
{
if(p(x + 1,y).flags & FLAMMABLE)
{
pset(x + 1,y,partFire);
return;
}
}
if(p(x,y - 1).flags & FLAMMABLE)
{
pset(x,y - 1,partFire);
return;
}
pset(x,y,partEmpty);
}
function main()
{
video_window(NULL,NULL,NULL,"Jump'n'run");
vec_set(screen_color,vector(128,0,0));
var x,y;
wait(1);
fps_max = 60;
mouse_mode = 4;
partEmpty.type = 0;
partEmpty.red = 0;
partEmpty.green = 0;
partEmpty.blue = 0;
partEmpty.eventDown = NULL;
partEmpty.eventUp = NULL;
partEmpty.flags = 0;
partEmpty.name = "Empty";
pData[0] = &partEmpty;
partDust.type = 1;
partDust.red = 255;
partDust.green = 222;
partDust.blue = 173;
partDust.eventDown = partDust_event;
partDust.eventUp = NULL;
partDust.flags = FLAMMABLE | SOLID;
partDust.name = "Dust";
pData[1] = &partDust;
partWater.type = 2;
partWater.red = 30;
partWater.green = 144;
partWater.blue = 255;
partWater.eventDown = partFluidBase_event;
partWater.eventUp = NULL;
partWater.flags = FLUID;
partWater.name = "Water";
pData[2] = &partWater;
partBlock.type = 3;
partBlock.red = 220;
partBlock.green = 220;
partBlock.blue = 220;
partBlock.eventDown = NULL;
partBlock.eventUp = NULL;
partBlock.flags = 0;
partBlock.name = "Block";
pData[3] = &partBlock;
partAcid.type = 4;
partAcid.red = 124;
partAcid.green = 252;
partAcid.blue = 0;
partAcid.eventDown = partAcid_event;
partAcid.eventUp = NULL;
partAcid.flags = FLUID;
partAcid.name = "Acid";
pData[4] = &partAcid;
partOil.type = 5;
partOil.red = 139;
partOil.green = 69;
partOil.blue = 19;
partOil.eventDown = partFluidBase_event;
partOil.eventUp = NULL;
partOil.flags = FLUID;
partOil.name = "Oil";
pData[5] = &partOil;
partClone.type = 6;
partClone.red = 255;
partClone.green = 215;
partClone.blue = 0;
partClone.eventDown = partClone_event;
partClone.eventUp = NULL;
partClone.flags = 0;
partClone.name = "Clone";
pData[6] = &partClone;
partVirus.type = 7;
partVirus.red = 255;
partVirus.green = 20;
partVirus.blue = 147;
partVirus.eventDown = partVirus_event;
partVirus.eventUp = NULL;
partVirus.flags = SOLID;
partVirus.name = "Virus";
pData[7] = &partVirus;
partFire.type = 8;
partFire.red = 255;
partFire.green = 69;
partFire.blue = 0;
partFire.eventDown = NULL;
partFire.eventUp = partFire_event;
partFire.flags = 0;
partFire.name = "Fire";
pData[8] = &partFire;
area.x = bmap_width(bmpOutput);
area.y = bmap_height(bmpOutput);
bounds.x = area.x - 1;
bounds.y = area.y - 1;
partSet = &partDust;
for(x = 0; x < area.x; x++)
{
for(y = 0; y < area.y; y++)
{
pset(x,y,partEmpty);
}
}
var lr = 0;
while(1)
{
if(key_1)
partSet = &partEmpty;
if(key_2)
partSet = &partDust;
if(key_3)
partSet = &partWater;
if(key_4)
partSet = &partBlock;
if(key_5)
partSet = &partAcid;
if(key_6)
partSet = &partOil;
if(key_7)
partSet = &partClone;
if(key_8)
partSet = &partVirus;
if(key_9)
partSet = &partFire;
if(partSet.name)
draw_text(partSet.name,4,4,COLOR_RED);
lr = random(100) < 50;
for(y = 0; y < area.y; y++)
{
if(lr)
{
for(x = 0; x < area.x; x++)
{
if(p(x,y).eventUp)
{
pEventUp(x,y);
}
}
}
else
{
for(x = bounds.x; x >= 0; x--)
{
if(p(x,y).eventUp)
{
pEventUp(x,y);
}
}
}
lr = !lr;
}
for(y = bounds.y; y >= 0; y--)
{
if(lr)
{
for(x = 0; x < area.x; x++)
{
if(p(x,y).eventDown)
{
pEventDown(x,y);
}
}
}
else
{
for(x = bounds.x; x >= 0; x--)
{
if(p(x,y).eventDown)
{
pEventDown(x,y);
}
}
}
lr = !lr;
}
//////////////////////////////////////////////////
bmap_fill(bmpOutput,vector(0,0,0),100);
var format = bmap_lock(bmpOutput,0);
for(x = 0; x < area.x; x++)
{
for(y = 0; y < area.y; y++)
{
pixel_to_bmap(bmpOutput,x,y,pixel_for_vec(p(x,y).blue,100,format));
}
}
bmap_unlock(bmpOutput);
panOutput.scale_x += mickey.z / 1200;
panOutput.scale_y += mickey.z / 1200;
panOutput.pos_x = screen_size.x / 2 - (area.x / 2) * panOutput.scale_x;
panOutput.pos_y = screen_size.y / 2 - (area.y / 2) * panOutput.scale_y;
wait(1);
}
}