2
0
mirror of https://frontier.innolan.net/github/amigaos-cross-toolchain6.git synced 2024-10-19 10:29:55 +00:00
Files
amigaos-cross-toolchain6/test/test6/test.c
2017-05-27 00:00:48 +02:00

417 lines
8.7 KiB
C
Executable File

#include "test.h"
extern object_t* game_player1;
extern object_t* game_player2;
int16_t object_count;
object_t* object_activeList;
static object_t* object_freeList;
static __section(random_c) object_t object_buffer[OBJECT_MAX_OBJECTS];
object_t* object_zBuffer[OBJECT_MAX_OBJECTS];
static object_t*
object_getFree(void)
{
object_t* entry = object_freeList;
object_freeList = object_freeList->next;
if (object_freeList) {
object_freeList->prev = 0;
}
#ifdef DEBUG
if (!entry) {
PANIC("object_getFree: empty list");
}
#endif
return entry;
}
static void
object_addFree(object_t* ptr)
{
object_count--;
if (object_freeList == 0) {
object_freeList = ptr;
ptr->next = 0;
ptr->prev = 0;
} else {
ptr->next = object_freeList;
ptr->next->prev = ptr;
ptr->prev = 0;
object_freeList = ptr;
}
}
static void
object_addToActive(object_t* ptr)
{
object_count++;
if (object_activeList == 0) {
object_activeList = ptr;
ptr->next = 0;
ptr->prev = 0;
} else {
ptr->next = object_activeList;
ptr->next->prev = ptr;
ptr->prev = 0;
object_activeList = ptr;
}
}
static void
object_removeFromActive(object_t* ptr)
{
if (ptr->prev == 0) {
object_activeList = ptr->next;
if (object_activeList) {
object_activeList->prev = 0;
}
} else {
ptr->prev->next = ptr->next;
if (ptr->next != 0) {
ptr->next->prev = ptr->prev;
}
}
}
void
object_setAnim(object_t* ptr, int16_t anim)
{
if (ptr->animId != anim) {
ptr->animId = anim;
ptr->anim = &object_animations[ptr->animId];
ptr->imageIndex = ptr->anim->start;
ptr->image = &object_imageAtlas[ptr->imageIndex];
ptr->frameCounter = 0;
}
}
void
object_free(object_t* ptr)
{
if (ptr->freeData) {
ptr->freeData(ptr->data);
}
object_removeFromActive(ptr);
object_addFree(ptr);
}
void
object_setAction(object_t* ptr, object_action_t action)
{
ptr->actionId = action;
object_setAnim(ptr, ptr->baseId + action);
}
void
object_updatePosition(uint16_t deltaT, object_t* ptr)
{
int16_t vx = ptr->velocity.x;
int16_t vy = ptr->velocity.y;
if (deltaT == 2) {
vx *= 2;
vy *= 2;
}
int16_t lastX = object_px(ptr);
int16_t lastY = object_py(ptr);
object_set_px(ptr, lastX + vx);
object_set_py(ptr, lastY + vy);
ptr->velocity.dx = object_px(ptr) - lastX;
ptr->velocity.dy = object_py(ptr) - lastY;
}
void
object_init(void)
{
object_count = 0;
object_activeList = 0;
object_freeList = &object_buffer[0];
object_freeList->prev = 0;
object_t* ptr = object_freeList;
for (int16_t i = 1; i < OBJECT_MAX_OBJECTS; i++) {
ptr->next = &object_buffer[i];
ptr->next->prev = ptr;
ptr = ptr->next;
}
ptr->next = 0;
}
static void
object_updateAnimation(uint16_t deltaT, object_t *ptr)
{
if (ptr->frameCounter >= ptr->anim->speed) {
ptr->imageIndex++;
ptr->frameCounter = 0;
if (ptr->imageIndex > ptr->anim->stop) {
ptr->imageIndex = ptr->anim->start;
}
ptr->image = &object_imageAtlas[ptr->imageIndex];
} else {
ptr->frameCounter+=deltaT;
}
}
void
object_clear(frame_buffer_t fb, int16_t ox, int16_t oy, int16_t ow, int16_t oh)
{
if (ow) {
int16_t sx = ox>>4;
int16_t sy = (oy)>>4;
int16_t ex = (ox+ow)>>4;
int16_t ey = (oy+oh)>>4;
for (int32_t x = sx; x <= ex; x++) {
for (int32_t y = sy; y <= ey; y++) {
uint16_t tile = level.tileAddresses[x][y];
int16_t screenX = 0xf+(x<<4)-game_cameraX-game_screenScrollX;
int16_t screenY = y << 4;
if (screenY >= 0 && screenX >= 0 && screenX <= SCREEN_WIDTH+TILE_WIDTH) {
gfx_quickRenderTile(fb, screenX, screenY, level.tileBitplanes+tile);
}
}
}
}
}
void
object_renderObject(frame_buffer_t fb, object_t* ptr)
{
if (!ptr->visible) {
return;
}
int16_t w = ptr->image->w;
int16_t h = ptr->image->h;
int16_t screenx = object_screenx(ptr);
int16_t screeny = object_screeny(ptr);
int16_t sx = ptr->image->x;
int16_t sy = ptr->image->y;
if (screenx < -TILE_WIDTH) {
int16_t tiles = (-screenx>>4)<<4;
sx += tiles;
w -= tiles ;
screenx += tiles;
}
if ((screenx+w) > SCREEN_WIDTH+TILE_WIDTH) {
int16_t tiles = (((screenx+w) -(SCREEN_WIDTH+TILE_WIDTH))>>4)<<4;
w -= tiles;
}
if (screeny < 0) {
sy -= screeny;
h += screeny;
screeny = 0;
}
if (w > 0 && h > 0) {
if (ptr->tileRender) {
gfx_setupRenderTile();
object_clear(fb, object_x(ptr)+ptr->image->dx, object_y(ptr)-h, w, h);
return;
}
gfx_renderSprite(fb, sx, sy, screenx, screeny, w, h);
}
}
static void
object_update(uint16_t deltaT)
{
object_t* ptr = object_activeList;
while (ptr) {
object_t* next = ptr->next;
if (ptr->update) {
ptr->update(deltaT, ptr);
}
if (object_get_state(ptr) == OBJECT_STATE_REMOVED) {
if (ptr->deadRenderCount == 2) {
if (ptr == game_player1) {
game_player1 = 0;
} else if (ptr == game_player2) {
game_player2 = 0;
}
object_free(ptr);
} else {
ptr->deadRenderCount++;
}
}
ptr = next;
}
}
static void
object_saveBackground(void)
{
object_t* ptr = object_activeList;
int16_t i = 0;
while (ptr != 0) {
object_zBuffer[i] = ptr;
i++;
ptr->save.position->x = object_x(ptr)+ptr->image->dx;
ptr->save.position->y = object_y(ptr)-ptr->image->h;
ptr->save.position->w = ptr->image->w;
ptr->save.position->h = ptr->image->h;
ptr->save.position = ptr->save.position == &ptr->save.positions[0] ? &ptr->save.positions[1] : &ptr->save.positions[0];
ptr = ptr->next;
}
}
void
object_render(frame_buffer_t fb, uint16_t deltaT)
{
object_update(deltaT);
object_restoreBackground(fb);
object_saveBackground();
// sort_z(object_count, object_zBuffer);
for (int16_t i = 0; i < object_count; i++) {
object_t* ptr = object_zBuffer[i];
if (object_get_state(ptr) != OBJECT_STATE_REMOVED) {
object_renderObject(fb, ptr);
object_updateAnimation(deltaT, ptr);
}
}
}
void
object_restoreBackground(frame_buffer_t fb)
{
object_t* ptr = object_activeList;
gfx_setupRenderTile();
while (ptr != 0) {
if (!ptr->tileRender) {
object_clear(fb, ptr->save.position->x, ptr->save.position->y, ptr->save.position->w, ptr->save.position->h);
}
ptr = ptr->next;
}
}
int16_t
object_collision(int16_t deltaT, object_t* a, object_collision_t* collision, uint16_t thresholdx, uint16_t thresholdy)
{
int16_t vy = a->velocity.y;
int16_t vx = a->velocity.x;
if (deltaT == 2) {
vx *= 2;
vy *= 2;
}
int16_t _collision = 0;
object_t* b = object_activeList;
collision->up = collision->down = collision->left = collision->right = 0;
#ifdef DEBUG
if (!game_collisions) {
return 0;
}
#endif
int16_t a_y = ((object_py(a) + vy) / OBJECT_PHYSICS_FACTOR);
int16_t a_x1 = (((object_px(a) + vx) / OBJECT_PHYSICS_FACTOR) + a->widthOffset)-thresholdx;
int16_t a_x2 = (((object_px(a) + vx) / OBJECT_PHYSICS_FACTOR) + (a->width - a->widthOffset)) + thresholdx;
while (b) {
if (b->collidable && b != a) {
int16_t b_y = ((object_y(b)));
if (abs(a_y - b_y) <= thresholdy) {
int16_t b_x1 = ((object_x(b))) + b->widthOffset;
int16_t b_x2 = ((object_x(b))) + (b->width - b->widthOffset);
if (a_x1 < b_x2 && a_x2 > b_x1) {
if (b_y >= a_y) {
collision->up = b;
} else if (b_y < a_y) {
collision->down = b;
}
if (b_x1 >= a_x1) {
collision->right = b;
} else if (b_x1 < a_x1) {
collision->left = b;
}
_collision = 1;
}
}
}
b = b->next;
}
return _collision;
}
NOINLINE object_t*
object_add(uint16_t id, uint16_t class, int16_t x, int16_t y, int16_t dx, int16_t anim, void (*update)(uint16_t deltaT, object_t* ptr), void* data, void (*freeData)(void*))
{
#ifdef DEBUG
if (object_count >= OBJECT_MAX_OBJECTS) {
PANIC("object_add: no free objects");
return 0;
}
#endif
object_t* ptr = object_getFree();
object_set_state(ptr, OBJECT_STATE_ALIVE);
ptr->class = class;
ptr->visible = 1;
ptr->id = id;
ptr->velocity.x = dx;
ptr->velocity.y = 0;
ptr->save.position = &ptr->save.positions[0];
ptr->save.positions[0].w = 0;
ptr->save.positions[1].w = 0;
ptr->anim = &object_animations[anim];
ptr->animId = anim;
ptr->baseId = anim;
ptr->imageIndex = ptr->anim->start;
ptr->image = &object_imageAtlas[ptr->imageIndex];
ptr->_px = x*OBJECT_PHYSICS_FACTOR;
ptr->_x = x;
ptr->_py = y*OBJECT_PHYSICS_FACTOR;
ptr->_y = y;
object_set_z(ptr, y);
ptr->frameCounter = 0;
ptr->deadRenderCount = 0;
ptr->update = update;
ptr->data = data;
ptr->freeData = freeData;
ptr->tileRender = 0;
ptr->collidable = (ptr->class == OBJECT_CLASS_FIGHTER || ptr->class == OBJECT_CLASS_THING);
object_addToActive(ptr);
return ptr;
}