2016-07-04 00:56:45 +02:00
/*! \file character.c
* \ brief Character and spritesheet functions .
*/
/*
* Copyright ( c ) Sebastian Krzyszkowiak < dos @ dosowisko . 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
2017-07-22 18:22:12 +02:00
* the Free Software Foundation ; either version 3 of the License , or
2016-07-04 00:56:45 +02:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2017-07-22 18:22:12 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2016-07-04 00:56:45 +02:00
*/
2017-09-10 21:35:14 +02:00
# include "internal.h"
# include "utils.h"
2016-07-04 00:56:45 +02:00
# include <allegro5/allegro_primitives.h>
# include <allegro5/allegro_ttf.h>
2018-02-09 03:34:50 +01:00
# include <math.h>
2016-09-08 00:32:21 +02:00
# include <stdio.h>
# include <string.h>
2016-07-04 00:56:45 +02:00
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void SelectSpritesheet ( struct Game * game , struct Character * character , char * name ) {
struct Spritesheet * tmp = character - > spritesheets ;
2018-03-21 02:05:22 +01:00
bool reversed = false ;
if ( name [ 0 ] = = ' - ' ) {
reversed = true ;
name + + ;
}
2016-07-04 00:56:45 +02:00
PrintConsole ( game , " Selecting spritesheet for %s: %s " , character - > name , name ) ;
if ( ! tmp ) {
PrintConsole ( game , " ERROR: No spritesheets registered for %s! " , character - > name ) ;
return ;
}
while ( tmp ) {
if ( ! strcmp ( tmp - > name , name ) ) {
character - > spritesheet = tmp ;
2017-09-10 21:35:14 +02:00
if ( character - > successor ) {
free ( character - > successor ) ;
}
2016-07-04 00:56:45 +02:00
if ( tmp - > successor ) {
character - > successor = strdup ( tmp - > successor ) ;
} else {
character - > successor = NULL ;
}
2018-03-21 02:05:22 +01:00
if ( character - > predecessor ) {
free ( character - > predecessor ) ;
}
if ( tmp - > predecessor ) {
character - > predecessor = strdup ( tmp - > predecessor ) ;
} else {
character - > predecessor = NULL ;
}
2018-02-10 04:29:57 +01:00
character - > repeats = tmp - > repeats ;
2018-03-21 02:05:22 +01:00
character - > pos = reversed ? ( tmp - > frameCount - 1 ) : 0 ;
character - > reversed = reversed ;
character - > reversing = tmp - > reversed ^ reversed ;
2018-03-20 21:39:37 +01:00
character - > frame = & tmp - > frames [ character - > pos ] ;
//character->bitmap = tmp->frames[character->pos].bitmap;
PrintConsole ( game , " SUCCESS: Spritesheet for %s activated: %s (%dx%d) " , character - > name , character - > spritesheet - > name , character - > spritesheet - > width , character - > spritesheet - > height ) ;
2016-07-04 00:56:45 +02:00
return ;
}
tmp = tmp - > next ;
}
PrintConsole ( game , " ERROR: No spritesheets registered for %s with given name: %s " , character - > name , name ) ;
}
2018-04-26 14:33:52 +02:00
SYMBOL_EXPORT void SwitchSpritesheet ( struct Game * game , struct Character * character , char * name ) {
int pos = character - > pos ;
SelectSpritesheet ( game , character , name ) ;
if ( pos < character - > spritesheets - > frameCount ) {
character - > pos = pos ;
character - > frame = & character - > spritesheet - > frames [ character - > pos ] ;
}
}
2018-02-10 04:29:57 +01:00
SYMBOL_EXPORT void EnqueueSpritesheet ( struct Game * game , struct Character * character , char * name ) {
2017-09-10 21:35:14 +02:00
if ( character - > successor ) {
free ( character - > successor ) ;
}
2016-07-04 00:56:45 +02:00
character - > successor = strdup ( name ) ;
}
2018-04-15 23:00:17 +02:00
SYMBOL_EXPORT struct Spritesheet * GetSpritesheet ( struct Game * game , struct Character * character , char * name ) {
struct Spritesheet * tmp = character - > spritesheets ;
while ( tmp ) {
if ( ! strcmp ( tmp - > name , name ) ) {
return tmp ;
}
tmp = tmp - > next ;
}
return NULL ;
}
2018-07-05 19:38:31 +02:00
SYMBOL_EXPORT void LoadSpritesheets ( struct Game * game , struct Character * character , void ( * progress ) ( struct Game * ) ) {
2016-07-04 00:56:45 +02:00
PrintConsole ( game , " Loading spritesheets for character %s... " , character - > name ) ;
2017-09-10 21:35:14 +02:00
struct Spritesheet * tmp = character - > spritesheets ;
2016-07-04 00:56:45 +02:00
while ( tmp ) {
2018-07-04 06:55:48 +02:00
PrintConsole ( game , " - %s " , tmp - > name ) ;
2018-03-20 21:39:37 +01:00
if ( ( ! tmp - > bitmap ) & & ( tmp - > file ) ) {
2017-09-10 22:07:02 +02:00
char filename [ 255 ] = { 0 } ;
2018-03-20 21:39:37 +01:00
snprintf ( filename , 255 , " sprites/%s/%s " , character - > name , tmp - > file ) ;
2016-07-04 00:56:45 +02:00
tmp - > bitmap = al_load_bitmap ( GetDataFilePath ( game , filename ) ) ;
2018-03-20 21:39:37 +01:00
tmp - > width = al_get_bitmap_width ( tmp - > bitmap ) / tmp - > cols ;
tmp - > height = al_get_bitmap_height ( tmp - > bitmap ) / tmp - > rows ;
}
for ( int i = 0 ; i < tmp - > frameCount ; i + + ) {
if ( ( ! tmp - > frames [ i ] . bitmap ) & & ( tmp - > frames [ i ] . file ) ) {
2018-07-05 01:03:45 +02:00
if ( game - > config . debug ) {
PrintConsole ( game , " - %s " , tmp - > frames [ i ] . file ) ;
}
2018-03-20 21:39:37 +01:00
char filename [ 255 ] = { 0 } ;
snprintf ( filename , 255 , " sprites/%s/%s " , character - > name , tmp - > frames [ i ] . file ) ;
tmp - > frames [ i ] . bitmap = al_load_bitmap ( GetDataFilePath ( game , filename ) ) ;
2018-06-03 03:39:11 +02:00
int width = al_get_bitmap_width ( tmp - > frames [ i ] . bitmap ) + tmp - > frames [ i ] . x ;
2018-03-20 21:39:37 +01:00
if ( width > tmp - > width ) {
tmp - > width = width ;
}
2018-06-03 03:39:11 +02:00
int height = al_get_bitmap_height ( tmp - > frames [ i ] . bitmap ) + tmp - > frames [ i ] . y ;
2018-03-20 21:39:37 +01:00
if ( height > tmp - > height ) {
tmp - > height = height ;
}
} else if ( ! tmp - > frames [ i ] . bitmap ) {
tmp - > frames [ i ] . bitmap = al_create_sub_bitmap ( tmp - > bitmap , tmp - > frames [ i ] . col * tmp - > width , tmp - > frames [ i ] . row * tmp - > height , tmp - > width , tmp - > height ) ;
}
2016-07-04 00:56:45 +02:00
}
2018-07-05 19:38:31 +02:00
if ( progress ) {
progress ( game ) ;
}
2016-07-04 00:56:45 +02:00
tmp = tmp - > next ;
}
2018-03-20 21:39:37 +01:00
if ( ( ! character - > spritesheet ) & & ( character - > spritesheets ) ) {
SelectSpritesheet ( game , character , character - > spritesheets - > name ) ;
}
2016-07-04 00:56:45 +02:00
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void UnloadSpritesheets ( struct Game * game , struct Character * character ) {
2016-07-04 00:56:45 +02:00
PrintConsole ( game , " Unloading spritesheets for character %s... " , character - > name ) ;
2017-09-10 21:35:14 +02:00
struct Spritesheet * tmp = character - > spritesheets ;
2016-07-04 00:56:45 +02:00
while ( tmp ) {
2018-03-20 21:39:37 +01:00
for ( int i = 0 ; i < tmp - > frameCount ; i + + ) {
if ( tmp - > frames [ i ] . bitmap ) {
al_destroy_bitmap ( tmp - > frames [ i ] . bitmap ) ;
}
}
2017-09-10 21:35:14 +02:00
if ( tmp - > bitmap ) {
al_destroy_bitmap ( tmp - > bitmap ) ;
}
2016-07-04 00:56:45 +02:00
tmp - > bitmap = NULL ;
tmp = tmp - > next ;
}
}
2018-03-20 21:39:37 +01:00
static long strtolnull ( const char * _nptr , long val ) {
if ( _nptr = = NULL ) {
return val ;
}
return strtol ( _nptr , NULL , 10 ) ;
}
static double strtodnull ( const char * _nptr , double val ) {
if ( _nptr = = NULL ) {
return val ;
}
return strtod ( _nptr , NULL ) ;
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void RegisterSpritesheet ( struct Game * game , struct Character * character , char * name ) {
struct Spritesheet * s = character - > spritesheets ;
2016-07-04 00:56:45 +02:00
while ( s ) {
if ( ! strcmp ( s - > name , name ) ) {
//PrintConsole(game, "%s spritesheet %s already registered!", character->name, name);
return ;
}
s = s - > next ;
}
PrintConsole ( game , " Registering %s spritesheet: %s " , character - > name , name ) ;
2017-09-10 22:07:02 +02:00
char filename [ 255 ] = { 0 } ;
2016-07-04 00:56:45 +02:00
snprintf ( filename , 255 , " sprites/%s/%s.ini " , character - > name , name ) ;
2017-09-10 21:35:14 +02:00
ALLEGRO_CONFIG * config = al_load_config_file ( GetDataFilePath ( game , filename ) ) ;
2016-07-04 00:56:45 +02:00
s = malloc ( sizeof ( struct Spritesheet ) ) ;
s - > name = strdup ( name ) ;
s - > bitmap = NULL ;
2018-03-20 21:39:37 +01:00
s - > frameCount = strtolnull ( al_get_config_value ( config , " animation " , " frames " ) , 0 ) ;
s - > rows = strtolnull ( al_get_config_value ( config , " animation " , " rows " ) , 0 ) ;
s - > cols = strtolnull ( al_get_config_value ( config , " animation " , " cols " ) , 0 ) ;
s - > flipX = strtolnull ( al_get_config_value ( config , " animation " , " flipX " ) , 0 ) ;
s - > flipY = strtolnull ( al_get_config_value ( config , " animation " , " flipY " ) , 0 ) ;
int blanks = strtolnull ( al_get_config_value ( config , " animation " , " blanks " ) , 0 ) ;
if ( s - > frameCount = = 0 ) {
s - > frameCount = s - > rows * s - > cols - blanks ;
2017-03-04 19:54:48 +01:00
} else {
2018-03-20 21:39:37 +01:00
s - > rows = floor ( sqrt ( s - > frameCount ) ) ;
2018-04-08 01:34:06 +02:00
s - > cols = ceil ( s - > frameCount / ( double ) s - > rows ) ;
2017-09-10 21:35:14 +02:00
}
2018-03-20 21:39:37 +01:00
s - > bidir = strtolnull ( al_get_config_value ( config , " animation " , " bidir " ) , 0 ) ;
s - > reversed = strtolnull ( al_get_config_value ( config , " animation " , " reversed " ) , 0 ) ;
s - > duration = strtodnull ( al_get_config_value ( config , " animation " , " duration " ) , 16.66 ) ;
2018-04-18 23:13:31 +02:00
s - > width = strtodnull ( al_get_config_value ( config , " animation " , " width " ) , 0 ) ;
s - > height = strtodnull ( al_get_config_value ( config , " animation " , " height " ) , 0 ) ;
2018-03-20 21:39:37 +01:00
2018-04-13 03:00:54 +02:00
s - > repeats = strtolnull ( al_get_config_value ( config , " animation " , " repeats " ) , - 1 ) ;
2018-03-20 21:39:37 +01:00
2017-09-10 21:35:14 +02:00
s - > successor = NULL ;
2018-03-20 21:39:37 +01:00
const char * successor = al_get_config_value ( config , " animation " , " successor " ) ;
2016-07-04 00:56:45 +02:00
if ( successor ) {
2018-03-20 21:39:37 +01:00
int len = strlen ( successor ) + 1 ;
s - > successor = malloc ( len * sizeof ( char ) ) ;
strncpy ( s - > successor , successor , len ) ;
}
2018-03-21 02:05:22 +01:00
s - > predecessor = NULL ;
const char * predecessor = al_get_config_value ( config , " animation " , " predecessor " ) ;
if ( predecessor ) {
int len = strlen ( predecessor ) + 1 ;
s - > predecessor = malloc ( len * sizeof ( char ) ) ;
strncpy ( s - > predecessor , predecessor , len ) ;
}
2018-03-20 21:39:37 +01:00
{
s - > file = NULL ;
const char * file = al_get_config_value ( config , " animation " , " file " ) ;
if ( file ) {
int len = strlen ( file ) + 1 ;
s - > file = malloc ( len * sizeof ( char ) ) ;
strncpy ( s - > file , file , len ) ;
}
}
s - > pivotX = strtodnull ( al_get_config_value ( config , " pivot " , " x " ) , 0.5 ) ;
s - > pivotY = strtodnull ( al_get_config_value ( config , " pivot " , " y " ) , 0.5 ) ;
s - > frames = malloc ( sizeof ( struct SpritesheetFrame ) * s - > frameCount ) ;
for ( int i = 0 ; i < s - > frameCount ; i + + ) {
char framename [ 255 ] ;
snprintf ( framename , 255 , " frame%d " , i ) ;
s - > frames [ i ] . duration = strtodnull ( al_get_config_value ( config , framename , " duration " ) , s - > duration ) ;
s - > frames [ i ] . bitmap = NULL ;
s - > frames [ i ] . x = strtolnull ( al_get_config_value ( config , framename , " x " ) , 0 ) ;
s - > frames [ i ] . y = strtolnull ( al_get_config_value ( config , framename , " y " ) , 0 ) ;
s - > frames [ i ] . flipX = strtolnull ( al_get_config_value ( config , framename , " flipX " ) , 0 ) ;
s - > frames [ i ] . flipY = strtolnull ( al_get_config_value ( config , framename , " flipY " ) , 0 ) ;
s - > frames [ i ] . file = NULL ;
const char * file = al_get_config_value ( config , framename , " file " ) ;
if ( file ) {
int len = strlen ( file ) + 1 ;
s - > frames [ i ] . file = malloc ( len * sizeof ( char ) ) ;
strncpy ( s - > frames [ i ] . file , file , len ) ;
}
if ( ! file ) {
s - > frames [ i ] . col = i % s - > cols ;
2018-04-08 01:34:06 +02:00
s - > frames [ i ] . row = i / s - > cols ;
2018-03-20 21:39:37 +01:00
const char * col_str = al_get_config_value ( config , filename , " col " ) ;
if ( col_str ) {
s - > frames [ i ] . col = strtol ( col_str , NULL , 10 ) ;
}
const char * row_str = al_get_config_value ( config , filename , " row " ) ;
if ( row_str ) {
s - > frames [ i ] . row = strtol ( row_str , NULL , 10 ) ;
}
}
2016-07-04 00:56:45 +02:00
}
2018-03-20 21:39:37 +01:00
2016-07-04 00:56:45 +02:00
s - > next = character - > spritesheets ;
character - > spritesheets = s ;
al_destroy_config ( config ) ;
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT struct Character * CreateCharacter ( struct Game * game , char * name ) {
2016-07-04 00:56:45 +02:00
PrintConsole ( game , " Creating character %s... " , name ) ;
2017-09-10 21:35:14 +02:00
struct Character * character = malloc ( sizeof ( struct Character ) ) ;
2016-07-04 00:56:45 +02:00
character - > name = strdup ( name ) ;
2018-03-20 21:39:37 +01:00
character - > frame = NULL ;
2018-02-10 04:29:57 +01:00
character - > spritesheet = NULL ;
character - > spritesheets = NULL ;
2016-07-04 00:56:45 +02:00
character - > pos = 0 ;
2018-03-20 21:39:37 +01:00
character - > delta = 0.0 ;
2018-02-10 04:29:57 +01:00
character - > successor = NULL ;
2018-03-21 02:05:22 +01:00
character - > predecessor = NULL ;
2016-07-04 00:56:45 +02:00
character - > x = - 1 ;
character - > y = - 1 ;
2018-02-10 04:29:57 +01:00
character - > tint = al_map_rgb ( 255 , 255 , 255 ) ;
2018-03-20 21:39:37 +01:00
//character->pivotX = 0.5;
//character->pivotY = 0.5;
2018-02-10 04:29:57 +01:00
character - > scaleX = 1.0 ;
character - > scaleY = 1.0 ;
character - > angle = 0 ;
2018-02-03 03:17:36 +01:00
character - > confineX = - 1 ;
character - > confineY = - 1 ;
2018-02-10 04:29:57 +01:00
character - > flipX = false ;
character - > flipY = false ;
2016-07-04 00:56:45 +02:00
character - > shared = false ;
2018-04-13 03:00:54 +02:00
character - > repeats = - 1 ;
2018-03-20 21:39:37 +01:00
character - > reversing = false ;
2018-02-10 04:29:57 +01:00
character - > parent = NULL ;
2018-03-20 21:39:37 +01:00
character - > hidden = false ;
2018-02-10 04:29:57 +01:00
character - > data = NULL ;
2018-03-20 21:39:37 +01:00
character - > callback = NULL ;
character - > callbackData = NULL ;
2018-07-05 16:43:13 +02:00
character - > destructor = NULL ;
2018-02-10 04:29:57 +01:00
2016-07-04 00:56:45 +02:00
return character ;
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void DestroyCharacter ( struct Game * game , struct Character * character ) {
2018-04-10 14:05:03 +02:00
PrintConsole ( game , " Destroying %scharacter %s... " , character - > shared ? " shared " : " " , character - > name ) ;
2018-07-05 16:43:13 +02:00
if ( character - > destructor ) {
character - > destructor ( game , character ) ;
}
2016-07-04 00:56:45 +02:00
if ( ! character - > shared ) {
struct Spritesheet * tmp , * s = character - > spritesheets ;
while ( s ) {
tmp = s ;
s = s - > next ;
2017-09-10 21:35:14 +02:00
if ( tmp - > successor ) {
free ( tmp - > successor ) ;
}
2018-03-21 02:05:22 +01:00
if ( tmp - > predecessor ) {
free ( tmp - > predecessor ) ;
}
2018-03-20 21:39:37 +01:00
if ( tmp - > file ) {
free ( tmp - > file ) ;
}
for ( int i = 0 ; i < tmp - > frameCount ; i + + ) {
if ( tmp - > frames [ i ] . bitmap ) {
al_destroy_bitmap ( tmp - > frames [ i ] . bitmap ) ;
}
if ( tmp - > frames [ i ] . file ) {
free ( tmp - > frames [ i ] . file ) ;
}
}
if ( tmp - > bitmap ) {
al_destroy_bitmap ( tmp - > bitmap ) ;
}
free ( tmp - > frames ) ;
2016-07-04 00:56:45 +02:00
free ( tmp - > name ) ;
free ( tmp ) ;
}
}
2017-09-10 21:35:14 +02:00
if ( character - > successor ) {
free ( character - > successor ) ;
}
2018-07-05 16:57:03 +02:00
if ( character - > predecessor ) {
free ( character - > predecessor ) ;
}
2016-07-04 00:56:45 +02:00
free ( character - > name ) ;
free ( character ) ;
}
2018-02-10 04:29:57 +01:00
SYMBOL_EXPORT void AnimateCharacter ( struct Game * game , struct Character * character , float delta , float speed_modifier ) {
2018-04-15 22:59:42 +02:00
if ( character - > hidden ) {
return ;
}
2018-03-20 21:39:37 +01:00
delta * = speed_modifier ;
character - > delta + = delta * 1000 ;
while ( character - > delta > = character - > spritesheet - > duration ) {
bool reachedEnd = false ;
character - > delta - = character - > spritesheet - > duration ;
if ( character - > reversing ) {
character - > pos - - ;
} else {
2016-07-04 00:56:45 +02:00
character - > pos + + ;
}
2018-03-20 21:39:37 +01:00
if ( character - > pos > = character - > spritesheet - > frameCount ) {
if ( character - > spritesheet - > bidir ) {
character - > pos - = 2 ;
character - > reversing = true ;
2018-03-21 02:05:22 +01:00
if ( character - > reversed ) {
reachedEnd = true ;
}
2018-03-20 21:39:37 +01:00
} else {
character - > pos = 0 ;
reachedEnd = true ;
}
}
if ( character - > pos < 0 ) {
2018-03-21 02:05:22 +01:00
if ( character - > spritesheet - > bidir ) {
character - > pos + = 2 ;
character - > reversing = false ;
if ( ! character - > reversed ) {
reachedEnd = true ;
}
} else {
character - > pos = character - > spritesheet - > frameCount - 1 ;
reachedEnd = true ;
}
2018-03-20 21:39:37 +01:00
}
if ( reachedEnd ) {
2018-04-13 03:00:54 +02:00
if ( character - > repeats > 0 ) {
2018-02-10 04:29:57 +01:00
character - > repeats - - ;
2018-03-20 21:39:37 +01:00
if ( character - > callback ) {
2018-04-15 23:00:53 +02:00
character - > callback ( game , character , NULL , character - > spritesheet , character - > callbackData ) ;
2018-03-20 21:39:37 +01:00
}
2018-03-21 02:05:22 +01:00
} else {
if ( ( ! character - > reversed ) & & ( character - > successor ) ) {
2018-04-15 23:00:53 +02:00
struct Spritesheet * old = character - > spritesheet ;
2018-03-21 02:05:22 +01:00
SelectSpritesheet ( game , character , character - > successor ) ;
if ( character - > callback ) {
2018-04-15 23:00:53 +02:00
character - > callback ( game , character , character - > spritesheet , old , character - > callbackData ) ;
2018-03-21 02:05:22 +01:00
}
2018-04-13 03:00:54 +02:00
} else if ( ( character - > reversed ) & & ( character - > predecessor ) ) {
2018-04-15 23:00:53 +02:00
struct Spritesheet * old = character - > spritesheet ;
2018-03-21 02:05:22 +01:00
SelectSpritesheet ( game , character , character - > predecessor ) ;
if ( character - > callback ) {
2018-04-15 23:00:53 +02:00
character - > callback ( game , character , character - > spritesheet , old , character - > callbackData ) ;
2018-03-21 02:05:22 +01:00
}
2018-04-13 03:00:54 +02:00
} else {
if ( character - > repeats = = 0 ) {
if ( character - > reversed ) {
character - > pos = 1 ;
} else {
character - > pos = character - > spritesheet - > frameCount - 1 ;
}
if ( character - > callback ) {
2018-04-15 23:00:53 +02:00
character - > callback ( game , character , NULL , character - > spritesheet , character - > callbackData ) ;
2018-04-13 03:00:54 +02:00
}
}
2018-03-20 21:39:37 +01:00
}
2016-07-04 00:56:45 +02:00
}
}
2018-04-13 03:00:54 +02:00
if ( character - > spritesheet - > frameCount = = 1 ) {
character - > pos = 0 ;
}
2016-07-04 00:56:45 +02:00
}
2018-03-20 21:39:37 +01:00
character - > frame = & character - > spritesheet - > frames [ character - > pos ] ;
2016-07-04 00:56:45 +02:00
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void MoveCharacter ( struct Game * game , struct Character * character , float x , float y , float angle ) {
2018-02-03 03:17:36 +01:00
MoveCharacterF ( game , character , x / ( float ) GetCharacterConfineX ( game , character ) , y / ( float ) GetCharacterConfineY ( game , character ) , angle ) ;
2016-08-26 23:52:32 +02:00
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void MoveCharacterF ( struct Game * game , struct Character * character , float x , float y , float angle ) {
2016-07-04 00:56:45 +02:00
character - > x + = x ;
character - > y + = y ;
character - > angle + = angle ;
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void SetCharacterPositionF ( struct Game * game , struct Character * character , float x , float y , float angle ) {
2016-07-04 00:56:45 +02:00
character - > x = x ;
character - > y = y ;
character - > angle = angle ;
}
2017-09-10 21:35:14 +02:00
SYMBOL_EXPORT void SetCharacterPosition ( struct Game * game , struct Character * character , float x , float y , float angle ) {
2018-02-03 03:17:36 +01:00
SetCharacterPositionF ( game , character , x / ( float ) GetCharacterConfineX ( game , character ) , y / ( float ) GetCharacterConfineY ( game , character ) , angle ) ;
2016-08-26 23:52:32 +02:00
}
2018-06-04 19:10:29 +02:00
SYMBOL_EXPORT ALLEGRO_TRANSFORM GetCharacterTransform ( struct Game * game , struct Character * character ) {
ALLEGRO_TRANSFORM transform ;
int w = character - > spritesheet - > width , h = character - > spritesheet - > height ;
al_identity_transform ( & transform ) ;
2018-07-04 19:08:39 +02:00
al_translate_transform ( & transform , - w / 2.0 , - h / 2.0 ) ;
2018-06-04 19:10:29 +02:00
al_scale_transform ( & transform , ( ( character - > flipX ^ character - > spritesheet - > flipX ^ character - > frame - > flipX ) ? - 1 : 1 ) , ( ( character - > flipY ^ character - > spritesheet - > flipY ^ character - > frame - > flipY ) ? - 1 : 1 ) ) ; // flipping; FIXME: should it be here or later?
2018-07-04 19:08:39 +02:00
al_translate_transform ( & transform , w / 2.0 , h / 2.0 ) ;
2018-06-04 19:10:29 +02:00
al_translate_transform ( & transform , character - > spritesheet - > frames [ character - > pos ] . x , character - > spritesheet - > frames [ character - > pos ] . y ) ; // spritesheet frame offset
al_translate_transform ( & transform , - w * character - > spritesheet - > pivotX , - h * character - > spritesheet - > pivotY ) ; // pivot
al_scale_transform ( & transform , character - > scaleX , character - > scaleY ) ;
al_rotate_transform ( & transform , character - > angle ) ;
al_translate_transform ( & transform , GetCharacterX ( game , character ) , GetCharacterY ( game , character ) ) ; // position
return transform ;
}
2018-02-10 04:29:57 +01:00
SYMBOL_EXPORT void DrawCharacter ( struct Game * game , struct Character * character ) {
2018-03-20 21:39:37 +01:00
if ( character - > hidden ) {
return ;
}
ALLEGRO_TRANSFORM current = * al_get_current_transform ( ) ;
2018-06-04 19:10:29 +02:00
ALLEGRO_TRANSFORM transform = GetCharacterTransform ( game , character ) ;
2018-03-20 21:39:37 +01:00
al_compose_transform ( & transform , & current ) ;
al_use_transform ( & transform ) ;
2018-03-21 02:15:34 +01:00
al_draw_tinted_bitmap ( character - > frame - > bitmap , character - > tint , 0 , 0 , 0 ) ;
2018-06-04 19:10:29 +02:00
2018-04-24 05:01:59 +02:00
/* al_hold_bitmap_drawing(false);
al_draw_filled_rectangle ( character - > spritesheet - > width * character - > spritesheet - > pivotX - 5 ,
character - > spritesheet - > height * character - > spritesheet - > pivotY - 5 ,
character - > spritesheet - > width * character - > spritesheet - > pivotX + 5 ,
character - > spritesheet - > height * character - > spritesheet - > pivotY + 5 ,
al_map_rgb ( 255 , 255 , 0 ) ) ; */
2018-03-20 21:39:37 +01:00
al_use_transform ( & current ) ;
2016-08-26 23:52:32 +02:00
}
2018-02-03 03:17:36 +01:00
SYMBOL_EXPORT void SetCharacterConfines ( struct Game * game , struct Character * character , int x , int y ) {
character - > confineX = x ;
character - > confineY = y ;
}
SYMBOL_EXPORT int GetCharacterConfineX ( struct Game * game , struct Character * character ) {
return ( character - > confineX > = 0 ) ? character - > confineX : game - > viewport . width ;
}
SYMBOL_EXPORT int GetCharacterConfineY ( struct Game * game , struct Character * character ) {
return ( character - > confineY > = 0 ) ? character - > confineY : game - > viewport . height ;
}
2018-02-10 04:29:57 +01:00
SYMBOL_EXPORT float GetCharacterX ( struct Game * game , struct Character * character ) {
2018-02-03 03:17:36 +01:00
return character - > x * GetCharacterConfineX ( game , character ) ;
2016-08-26 23:52:32 +02:00
}
2018-02-10 04:29:57 +01:00
SYMBOL_EXPORT float GetCharacterY ( struct Game * game , struct Character * character ) {
2018-02-03 03:17:36 +01:00
return character - > y * GetCharacterConfineY ( game , character ) ;
2016-08-26 23:52:32 +02:00
}
2018-03-15 00:46:52 +01:00
static void SortTwoFloats ( float * v1 , float * v2 ) {
float pom = * v1 ;
2018-06-04 19:10:29 +02:00
if ( * v1 > * v2 ) {
2018-03-15 00:46:52 +01:00
* v1 = * v2 ;
* v2 = pom ;
}
}
SYMBOL_EXPORT bool IsOnCharacter ( struct Game * game , struct Character * character , float x , float y , bool pixelperfect ) {
2018-03-20 21:39:37 +01:00
if ( character - > hidden ) {
return false ;
}
2018-03-15 00:46:52 +01:00
2018-06-04 19:10:29 +02:00
float x1 = 0.0 , y1 = 0.0 ;
float x2 = character - > spritesheet - > width , y2 = character - > spritesheet - > height ;
2018-04-10 05:18:29 +02:00
2018-06-04 19:10:29 +02:00
ALLEGRO_TRANSFORM transform = GetCharacterTransform ( game , character ) ;
2018-03-15 00:46:52 +01:00
al_transform_coordinates ( & transform , & x1 , & y1 ) ;
al_transform_coordinates ( & transform , & x2 , & y2 ) ;
SortTwoFloats ( & x1 , & x2 ) ;
SortTwoFloats ( & y1 , & y2 ) ;
2018-06-04 19:10:29 +02:00
2018-02-09 03:34:50 +01:00
bool test = ( ( x > = x1 ) & & ( x < = x2 ) & & ( y > = y1 ) & & ( y < = y2 ) ) ;
if ( test & & pixelperfect ) {
2018-06-04 19:10:29 +02:00
al_invert_transform ( & transform ) ;
al_transform_coordinates ( & transform , & x , & y ) ;
2018-03-20 21:39:37 +01:00
ALLEGRO_COLOR color = al_get_pixel ( character - > frame - > bitmap , x , y ) ;
2018-02-09 03:34:50 +01:00
return ( color . a > 0.0 ) ;
}
return test ;
2016-08-29 23:44:15 +02:00
}
2018-03-20 21:39:37 +01:00
2018-07-04 06:55:12 +02:00
SYMBOL_EXPORT void ShowCharacter ( struct Game * game , struct Character * character ) {
2018-03-20 21:39:37 +01:00
character - > hidden = false ;
}
2018-07-04 06:55:12 +02:00
SYMBOL_EXPORT void HideCharacter ( struct Game * game , struct Character * character ) {
2018-03-20 21:39:37 +01:00
character - > hidden = true ;
}