#include "ennemi.h" #include "mario.h" #include "box.h" #include "tile.h" #include "world.h" #include "score.h" #include #include #include #include #include #include /** properties **/ const int ennemi_widths [NOMBRE_ENNEMIS] = {0, 8, 8, 8, 8 , 8, 8}; const int ennemi_heights[NOMBRE_ENNEMIS] = {0, 8, 8, 8, 8, 8, 8}; /** ram storage **/ ennemi_t * ennemis_global=0; static int ennemis_global_size=0; int ennemiesNumber() { return ennemis_global_size; } void ennemiesInit(ennemi_t * table, int s) { if (ennemis_global) freeProf(ennemis_global); ennemis_global_size = ennemis_global = 0; // reset if (s==0) return; int const size = sizeof(ennemi_t) * s; if ((ennemis_global = mallocProf(size)) == 0) mallocError(); ennemis_global_size = s; memcpy(ennemis_global, table, size); } void ennemiDisplay(ennemi_t const * e) { if (e->type == NONE) return; if (e->b.x <= cameraX(0) - e->b.w || e->b.x >= cameraX(0) + 127) return; // do not draw if out of the screen {// draw int tx=0, ty=0, dsx=0, dsy=0; tileset_t t={0, ennemi_widths[e->type], ennemi_heights[e->type], 1}; switch (e->type) { case GOOMBA_ID: { extern image_t img_goomba; t.sheet=&img_goomba; tx = e->life*(1+(time_id/10)%2); } break; case KOOPA_V_ID: { extern image_t img_koopa_verte; t.sheet=&img_koopa_verte; t.height=ennemi_heights[KOOPA_V_ID]+ennemi_heights[KOOPA_V_ID]/2; tx = (1+e->p1)+(time_id/8)%2; } break; case KOOPA_R_ID: { extern image_t img_koopa_rouge; t.sheet=&img_koopa_rouge; t.height=ennemi_heights[KOOPA_R_ID]+ennemi_heights[KOOPA_R_ID]/2; tx = (1+e->p1)+(time_id/8)%2; } break; case CARAPACE_VERTE: { extern image_t img_carapace_verte; t.sheet=&img_carapace_verte; t.height=ennemi_heights[CARAPACE_VERTE]+ennemi_heights[CARAPACE_VERTE]/8; } break; case CARAPACE_ROUGE: { extern image_t img_carapace_rouge; t.sheet=&img_carapace_rouge; t.height=ennemi_heights[CARAPACE_ROUGE]+ennemi_heights[CARAPACE_ROUGE]/8; } break; case PLANTE_ID: { extern image_t img_plante; t.sheet=&img_plante; t.width*=2; dsx=-4; } } tileDraw(e->b.x-cameraX(0)+dsx, e->b.y-cameraY(mario.p.y)+dsy, &t, tx, ty); } } void plante_tour(ennemi_t *e) { if (e->type==PLANTE_ID) { e->p1++; e->p1%=PLANTE_NLAPS; // En attente if (0<=e->p1 && e->p1<35) if (abs(mario.p.x-e->b.x)<15) e->p1=0; if (35<=e->p1 && e->p1<58) { if ((e->p1+1)%3==0) e->b.y++; } if (58 <= e->p1 && e->p1 < 75){} // plante en attente en haut if (75 <= e->p1 && e->p1 < 98) { if (e->p1%3==0) e->b.y--; } } } bool ennemi_check_collision(ennemi_t *e) { return (boxContact(&e->b, &mario.p)); } void hurtMario() { if (mario.p.h==M_SMALL && mario.immunity==0) {mario.dead=1;finish_level=0;} else marioSmaller(); } void ennemiMove(ennemi_t *e) { if (!(e->b.x<=cameraX(0)-e->b.w || e->b.x>=cameraX(0)+127)) e->discovered=1; // for security, tag as discover all drawed ennemies if (e->life==DEAD && e->type!=NONE) // dying animation { if (e->p1==0) { e->b.vx=2*sgn(e->b.vx); e->b.vy=5; } e->p1++; e->b.vy--; e->b.y+=e->b.vy; e->b.x+=e->b.vx; if (e->p1>=30) e->type=NONE; // died 1.5 sec before } if (e->b.xb.x>cameraX()-30) e->discovered=1; //if (e->b.x+e->b.w<=worldGetCell_real_x0()) // e->type=NONE; if (e->discovered==0) return; if (e->life==DEAD) return; // e->type=NONE; if (e->type==NONE) return; bool e_hitMario=ennemi_check_collision(e); if (e_hitMario&&mario.starMode) { e->life=DEAD; e->p1=0; scoreAdd(KILL_ENNEMI); return; } for (int i=0; itype!=NONE) { e->b.x+=sgn(e->b.vx)*(abs(e->b.vx)+(time_id%2))/2; const int contact=boxContact(&e->b, &t->b); e->b.x-=sgn(e->b.vx)*(abs(e->b.vx)+(time_id%2))/2; if (contact && t->life!=DEAD) { if (e->type!=CARAPACE_VERTE && e->type!=CARAPACE_ROUGE) { e->b.vx=0; e->b.vy=0; } else { if (t->type==CARAPACE_VERTE || t->type==CARAPACE_ROUGE) { e->p1*=-1; e->b.vx=6*e->p1; } else { t->life=DEAD; t->p1=0; scoreAdd(KILL_ENNEMI); } } } } } int previous_case=-5; for (int j=0; jb.h; j++) { if ((e->b.x+j)/8!=previous_case) { previous_case=(e->b.x+j)/8; gift_t * c=(gift_t *)worldGetCell(e->b.x+j, e->b.y-1); if ((c->type==GIFT || c->type==BRICK) && (c->time_hit_id || c->state) && e->life!=DEAD) { e->life=e->p1=DEAD; scoreAdd(KILL_ENNEMI); break; } } } if (e->b.y<0) e->type=NONE; const bool mario_fatal_hit = (mario.p.last_vy<=-2 || mario.p.vy<=-2); switch (e->type) // move { case KOOPA_R_ID: boxMove(&e->b); if (e->b.vx) { // demi tour si au dessus du vide int s=-1; if (e->b.vx>0) s=e->b.w; if (worldGetCellCategory(e->b.x+s, e->b.y-1)==CTG_EMPTY && sgn(e->b.vx)==sgn(s)) e->b.vx=(e->p1*=-1); } // fall through case GOOMBA_ID: case KOOPA_V_ID: if (e->type!=KOOPA_R_ID) boxMove(&e->b); if (e->b.vx==0) // demi tour si mur { if (e->p1==0) e->b.vx=e->p1=-1; else e->b.vx=(e->p1*=-1); } break; case CARAPACE_VERTE: case CARAPACE_ROUGE: boxMove(&e->b); if (e->b.vx==0) { if (e->p1<2) { e->p1*=-1; e->b.vx=6*e->p1; } } if (e->p1>=2) { if ((e->p1++)==80) { // transformation carapace->koopa e->type--; e->b.h=ennemi_heights[e->type]; e->p1=e->b.vx=0; } } break; case PLANTE_ID: plante_tour(e); } if (e_hitMario && mario_fatal_hit) switch (e->type) // mario attacks { case GOOMBA_ID: e->life=DEAD; e->p1=0; scoreAdd(KILL_ENNEMI); mario.p.vy=4; mario.p.y=e->b.y+ennemi_heights[e->type]+1; break; case KOOPA_V_ID: case KOOPA_R_ID: e->type++; e->b.h=ennemi_heights[e->type]; e->p1=2; e->b.vx=0; scoreAdd(KILL_ENNEMI); mario.p.vy=6; mario.p.y=e->b.y+ennemi_heights[e->type]+1; break; case CARAPACE_VERTE: case CARAPACE_ROUGE: if (e->p1==0 || e->p1>=2) { if (mario.p.x>=e->b.x) e->p1=-1; if (mario.p.x<=e->b.x) e->p1=1; e->b.vx=6*e->p1; mario.p.vy=6; mario.p.y=e->b.y+ennemi_heights[CARAPACE_VERTE]; } else { e->p1=e->b.vx=mario.p.vx=0; mario.p.vy=6; mario.p.y=e->b.y+ennemi_heights[CARAPACE_VERTE]+1; } break; case PLANTE_ID: hurtMario(); break; } else if (e_hitMario) switch (e->type) // hurt mario { case GOOMBA_ID: case KOOPA_V_ID: case KOOPA_R_ID: hurtMario(); break; case CARAPACE_VERTE: case CARAPACE_ROUGE: if (e->p1==0 || e->p1>=2) { if (mario.p.x>=e->b.x) e->p1=-1; else e->p1=1; e->b.vx=6*e->p1; if (mario_fatal_hit) { mario.p.vy=6; mario.p.y=e->b.y+ennemi_heights[CARAPACE_VERTE]; } else { // mario bounce if (mario.p.x>=e->b.x) mario.p.x=e->b.x+e->b.w; else mario.p.x=e->b.x-mario.p.w; mario.p.vx=0; } } else hurtMario(); break; case PLANTE_ID: hurtMario(); break; } } void ennemiesDisplay() { for (int i=0; i