304 lines
8.4 KiB
C
304 lines
8.4 KiB
C
/***************************************************************************
|
|
paddle.c - description
|
|
-------------------
|
|
begin : Fri Sep 7 2001
|
|
copyright : (C) 2001 by Michael Speck
|
|
email : kulkanie@gmx.net
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "../client/lbreakout.h"
|
|
#include "shots.h"
|
|
#include "paddle.h"
|
|
|
|
extern Game *cur_game;
|
|
int paddle_cw = 18, paddle_ch = 18; /* size of a paddle component */
|
|
|
|
/*
|
|
====================================================================
|
|
Create/delete a paddle. x is centered assuming a screen width of
|
|
640. ball_ammo is the number of additional balls paddle
|
|
may bring to game.
|
|
====================================================================
|
|
*/
|
|
Paddle* paddle_create(
|
|
int score, int type, int y, int size, int min_size, int max_size, int ball_ammo )
|
|
{
|
|
Paddle *paddle = salloc( 1, sizeof( Paddle ) );
|
|
delay_set( &paddle->resize_delay, 40 );
|
|
paddle->score = score;
|
|
paddle->len = size;
|
|
paddle->start_len = size;
|
|
paddle->min_len = min_size;
|
|
paddle->max_len = max_size;
|
|
paddle->w = (paddle->len + 2) * paddle_cw;
|
|
paddle->wanted_w = paddle->w;
|
|
paddle->h = paddle_ch;
|
|
paddle->y = y;
|
|
paddle->type = type;
|
|
if ( paddle->type == PADDLE_TOP )
|
|
paddle->wall_y = 0;
|
|
else
|
|
paddle->wall_y = 480 - BRICK_HEIGHT;
|
|
paddle->wall_alpha = 0;
|
|
paddle->x = ((MAP_WIDTH * BRICK_WIDTH) - paddle->w) / 2; /* centered */
|
|
paddle->cur_x = paddle->x;
|
|
paddle->friction = 0.3;
|
|
paddle->friction_delay = 0;
|
|
/* reset weapon */
|
|
paddle->weapon_ammo = PADDLE_WEAPON_AMMO;
|
|
/* reset slime&frozen */
|
|
paddle->slime = 0;
|
|
paddle->frozen = 0;
|
|
/* attract */
|
|
paddle->attract = ATTRACT_NONE;
|
|
/* no ivisiblivty */
|
|
paddle->invis = 0;
|
|
/* ammo */
|
|
paddle->ball_ammo = ball_ammo;
|
|
paddle->start_ball_ammo = ball_ammo;
|
|
/* ammo display */
|
|
paddle->ball_ammo_disp_y = 4;
|
|
if ( paddle->type == PADDLE_BOTTOM )
|
|
paddle->ball_ammo_disp_y += (MAP_HEIGHT-1)*BRICK_HEIGHT;
|
|
|
|
return paddle;
|
|
}
|
|
void paddle_delete( Paddle *paddle )
|
|
{
|
|
if ( paddle ) free( paddle );
|
|
}
|
|
void paddle_reset( Paddle *paddle )
|
|
{
|
|
/* bad hack, isn't it? */
|
|
Paddle *new = paddle_create(
|
|
0/*clear score*/, paddle->type, paddle->y, paddle->start_len,
|
|
paddle->min_len, paddle->max_len, paddle->start_ball_ammo );
|
|
*paddle = *new;
|
|
paddle_delete( new );
|
|
}
|
|
|
|
void paddle_freeze( Paddle *paddle, int freeze )
|
|
{
|
|
paddle->frozen = freeze;
|
|
/* Goddammit what a shitty hack!!! hope I never change input stuff
|
|
again. but who cares anyway? isn't this source all screwed up
|
|
already? so let's go on until chaos reigns!!! multiple exclamation
|
|
marks are a sure sign of a deseased mind, I read somewhere. This
|
|
is not true!!! I am NOT not mental!!! Hey, if you read this, drop
|
|
me a note. Just curious whether someone ever happened to do so. */
|
|
SDL_GetRelativeMouseState( &freeze, &freeze );
|
|
}
|
|
void paddle_set_slime( Paddle *paddle, int slime )
|
|
{
|
|
paddle->slime = slime;
|
|
}
|
|
int paddle_slimy( Paddle *paddle )
|
|
{
|
|
return paddle->slime;
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Set if paddle attracts boni/mali or none.
|
|
====================================================================
|
|
*/
|
|
void paddle_set_attract( Paddle *paddle, int attract )
|
|
{
|
|
paddle->attract = attract;
|
|
/* no graphical change yet */
|
|
}
|
|
int paddle_attract_malus( Paddle *paddle )
|
|
{
|
|
return ( paddle->attract == ATTRACT_MALUS );
|
|
}
|
|
int paddle_attract_bonus( Paddle *paddle )
|
|
{
|
|
return ( paddle->attract == ATTRACT_BONUS );
|
|
}
|
|
int paddle_check_attract( Paddle *paddle, int type )
|
|
{
|
|
switch ( type ) {
|
|
/* bonus */
|
|
case EX_SCORE200:
|
|
case EX_SCORE500:
|
|
case EX_SCORE1000:
|
|
case EX_SCORE2000:
|
|
case EX_SCORE5000:
|
|
case EX_SCORE10000:
|
|
case EX_GOLDSHOWER:
|
|
case EX_LENGTHEN:
|
|
case EX_LIFE:
|
|
case EX_SLIME:
|
|
case EX_METAL:
|
|
case EX_BALL:
|
|
case EX_WALL:
|
|
case EX_WEAPON:
|
|
case EX_SLOW:
|
|
case EX_JOKER:
|
|
case EX_EXPL_BALL:
|
|
case EX_BONUS_MAGNET:
|
|
if ( paddle_attract_bonus( paddle ) )
|
|
return 1;
|
|
return 0;
|
|
/* penalty */
|
|
case EX_SHORTEN:
|
|
case EX_FAST:
|
|
/*
|
|
case EX_SPIN_RIGHT:
|
|
case EX_SPIN_LEFT:
|
|
*/
|
|
case EX_MALUS_MAGNET:
|
|
case EX_WEAK_BALL:
|
|
case EX_DARKNESS:
|
|
case EX_GHOST_PADDLE:
|
|
case EX_FROZEN:
|
|
if ( paddle_attract_malus( paddle ) )
|
|
return 1;
|
|
return 0;
|
|
/* neutral */
|
|
case EX_DISABLE:
|
|
case EX_CHAOS:
|
|
case EX_TIME_ADD:
|
|
case EX_RANDOM:
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
(De)activate ghostly behaviour: paddle is only seen when moved at
|
|
maximum 200ms before.
|
|
====================================================================
|
|
*/
|
|
void paddle_set_invis( Paddle *paddle, int invis )
|
|
{
|
|
if ( invis ) paddle->invis_delay = PADDLE_INVIS_DELAY;
|
|
paddle->invis = invis;
|
|
}
|
|
int paddle_solid( Paddle *paddle )
|
|
{
|
|
/* does paddle is visible? */
|
|
if ( !paddle->invis ) return 1;
|
|
if ( paddle->invis_delay ) return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Init paddle resize (the change between wanted_w and w MUST be
|
|
even (else the paddle shrinks til eternity)
|
|
====================================================================
|
|
*/
|
|
int paddle_init_resize( Paddle *paddle, int c )
|
|
{
|
|
/* resize possbile */
|
|
if ( paddle->len + c > paddle->max_len || paddle->len + c < paddle->min_len )
|
|
return 0;
|
|
/* get wanted width */
|
|
paddle->len += c;
|
|
paddle->wanted_w = (paddle->len + 2) * paddle_cw;
|
|
/* reset delay */
|
|
delay_reset( &paddle->resize_delay );
|
|
return 1;
|
|
}
|
|
/*
|
|
====================================================================
|
|
Actually resize paddle and return the -1 for shrinkage and 1
|
|
for expansion.
|
|
====================================================================
|
|
*/
|
|
int paddle_resize( Paddle *paddle, int ms )
|
|
{
|
|
if ( paddle->w == paddle->wanted_w ) return 0;
|
|
if ( !delay_timed_out( &paddle->resize_delay, ms ) ) return 0;
|
|
/* change size and position */
|
|
if ( paddle->w < paddle->wanted_w ) {
|
|
paddle->w += 2;
|
|
paddle->cur_x -= 1;
|
|
paddle->x = (int)paddle->cur_x;
|
|
/* check range */
|
|
if (paddle->x < BRICK_WIDTH)
|
|
paddle->x = BRICK_WIDTH;
|
|
if (paddle->x + paddle->w > 640 - BRICK_WIDTH)
|
|
paddle->x = 640 - BRICK_WIDTH - paddle->w;
|
|
return 1;
|
|
}
|
|
else {
|
|
paddle->w -= 2;
|
|
paddle->cur_x += 1;
|
|
paddle->x = (int)paddle->cur_x;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Update paddle resize and fire weapon.
|
|
====================================================================
|
|
*/
|
|
void paddle_update( Paddle *paddle, int ms )
|
|
{
|
|
Ball *ball;
|
|
int result;
|
|
|
|
/* invisiblity */
|
|
if ( paddle->invis ) /* extra active */
|
|
if ( paddle->invis_delay > 0 && (paddle->invis_delay-=ms) <= 0 )
|
|
paddle->invis_delay = 0;
|
|
|
|
/* handle weapon */
|
|
if ( paddle->weapon_inst ) {
|
|
if ( paddle->fire_left || paddle->fire_right )
|
|
if ( paddle->weapon_ammo > 0 )
|
|
if ( (paddle->weapon_fire_delay-=ms) <= 0 ) {
|
|
paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
|
|
shot_create( paddle );
|
|
paddle->weapon_ammo--;
|
|
}
|
|
}
|
|
|
|
/* check for resize */
|
|
if ( ( result = paddle_resize( paddle, ms ) ) ) {
|
|
list_reset( cur_game->balls );
|
|
while ( ( ball = list_next( cur_game->balls ) ) )
|
|
/* adjust attached balls */
|
|
if ( ball->attached && ball->paddle == paddle ) {
|
|
if ( result < 0 ) {
|
|
/* shrinked */
|
|
if ( ball->cur.x > ( paddle->w >> 1 ) ) {
|
|
ball->cur.x -= 2;
|
|
ball->x = (int)ball->cur.x;
|
|
}
|
|
}
|
|
else {
|
|
/* expanded */
|
|
if ( ball->cur.x > ( paddle->w >> 1 ) ) {
|
|
ball->cur.x += 2;
|
|
ball->x = (int)ball->cur.x;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
====================================================================
|
|
De/Activate weapon
|
|
====================================================================
|
|
*/
|
|
void weapon_install( Paddle *paddle, int install )
|
|
{
|
|
if ( install ) paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
|
|
paddle->weapon_inst = install;
|
|
}
|
|
|