You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

801 lines
19 KiB
C++

//
// G A M E.O.N.E - LOW LEVEL LIB V1.0
// Copyright (C) 2001 LEVEL ONE ENTERTAINMENT,
// Licensed under the terms of LGPL.
//:---------------------------------------------------------------------------
//:Description
//
// BASE CLASS ACTOR, CROOT, CSTABACTION
//
// CActor : CStabAction, CRoot
//
// CActor
// +--CRoot
//
//
// CStabAction
// +--CStabAction_SetPosition
// +--CStabAction_SetViewAngle
// +--CStabAction_SetGravity
// +--CStabAction_SetGravityPtr
// +--CStabAction_Wait
// +--CStabAction_MSG
// +--CStabAction_RotateTo
// | +--CStabAction_RotateDir
// |
// +--CStabAction_ScaleTimed
// +--CStabAction_FadeTimed
// |
// +--CStabAction_MoveTimed
// | +--CStabAction_MoveTarget
// | +--CStabAction_MoveDirection
// | +--CStabAction_OffsetTimed
// | +--CStabAction_OffsetTarget
// |
// +--CStabAction_MoveTimedEase
// |
// +--CStabAction_Label
// +--CStabAction_JMP
// +--CStabAction_KILL
//
#ifndef ACTOR_H
#define ACTOR_H
#include "../lib_base.h"
#include "../llgfx.h"
#include "../llqueue.h"
#include "../llqueue_squeue.h"
#include "../llqueue_dequeue.h"
#include "../llqueue_str_array.h"
#include "../ll3d_vec2.h"
#include "../llgfx_blit.h"
#include "../llfile.h"
#include "../llmem.h"
#include <string.h>
using namespace ll3d; // probs mit arm gcc?
#define ITERATE_QUEUE(a,q) q.Reset();while(a=q.Next())//
#define ITERATE_LIST(node,li) for(node=li.GetFirst();node;node=node->GetNext())//
class CStabAction;
class CRoot;
class CActor
{
public:
CActor();
CActor(int type);
virtual ~CActor();
virtual void Action(float delta);
virtual void Draw(llgfx_id id);
virtual void SetPos(float x, float y);
virtual void SetPos(int x, int y);
int GetXPos() { return (int)m_position.m_u; };
int GetYPos() { return (int)m_position.m_v; };
virtual bool TestCollisionRect(CActor *actor_with);
virtual bool TestCollisionCircle(CActor *actor_with);
virtual void AddScore(int score);
virtual bool Message(const char *Type);
virtual void SendMsg(const char *msg);
virtual CActor * IsActor( const char *name); // returned sich selbst wenn name entspricht
virtual void SetDirectionD( float deg );
virtual void SetDirectionR( float rad );
virtual void InitTarget(float time, float target_x, float target_y );
virtual void InitTarget(float time, CVec2f &targetpos );
virtual void InitMove(float x_velocity, float y_velocity );
virtual void InitMove(CVec2f &targetpos, float velocity );
virtual bool MoveToTarget(float delta); // returned true wenn target erreicht
virtual bool MoveToTarget(float delta, CVec2f &current_pos, CVec2f &target_pos, CVec2f &direction);
virtual void Move(float delta);
virtual void GetBoundingRect(llgfx_sRECT *rect);
virtual void RotateModel(float angle); // winkel in radians
virtual void RotateLocal(float angle); // winkel in radians
float GetAngleToPoint(float x, float y);
void InitTargetAngleD(float time, float new_angle); // newAngle in degree
void InitTargetAngleR(float time, float new_angle); // newAngle in radians
float GetViewAngleD();
float GetViewAngleR();
virtual bool RotateToTargetAngle(float delta); // return true wenn target angle erreicht
void SetViewAngleD( float degree );
void PlusViewAngleD( float degree );
void MinusViewAngleD( float degree );
void PlusViewAngleR( float radians );
void MinusViewAngleR( float radians );
void SetViewAngleR( float radians );
void AddChild(CActor * actor );
void SetParent(CActor * actor );
void RemoveParent();
void RemoveChild(CActor * actor);
squeue<CStabAction> m_script;
CStabAction * m_cur_script;
squeue<CStabAction> m_actions;
queue<CActor> m_childs;
CActor *m_parent; // Wenn ungleich 0 dann muss drawchild() aufgerufen werden
static CRoot *gl_root; // Root Actor
CVec2f m_position; // Playfield Position
CVec2f m_screen_pos; // Ziel Position (Bildschirm)
CVec2f m_xyoffset; // Drawing Offset
CVec2f m_target_position; // Ziel Playfield Position f<>r move_target
CVec2f m_direction; // Richtungsvektor
CVec2f m_old_position; // Alte Playfield Position
CVec2f m_scale; // x,y scale faktor
float m_velocity; // Geschwindigkeit
float m_acceleration; // Beschleunigung pro Sekunde
float m_view_angle; // 0 = Zeigt nach oben
float m_cos_radians;
float m_sin_radians;
float m_target_angle; // f<>r RotateTo
float m_rdir; // rotation
float m_rtleft; // zeit <20>brig f<>r zielrotation
float m_health; // Anzahl Health
float m_power; // Power bei Kollision
int m_score; // Jeder Actor hat einen Score
float m_lifetime; // Actor wird entfernt wenn lifetime unter 0 geht
float m_radius; // F<>r Kollisionsabfrage
llgfx_sRECT m_bounding_rect; // F<>r Kollisionsabfrage
llgfx_sRECT m_position_rect; // posrect = m_boudingrect + m_position
// Muss durch Action() gesetzt werden
int m_blitflag; // blitflag
llgfx_sBLITFX m_blitfx; // blitfx
int m_type; // type f<>r z.b. CreateUpdatePacket
int m_id; // F<>r Kollision etc.
// Object Typ Informationen
// Jede Klasse die die Funktion Message ableitet muss
// objtype und namen im Konstruktor setzen
// Messagesyntax ist = "objname::*", * steht f<>r die Message
char m_obj_name[64]; // Objekt name oder Objekt nummer
int m_obj_namelen; // l<>nge des Obektnames
virtual void ParseSkriptFile(const char *filename );
virtual void ParseLine( const char * line );
void ClearScript();
static float GetAngle(CActor *A, CActor *B);
private:
void Draw();
void ParseCCmds(const char * line );
void ParseFCmds(const char * line );
void ParseMCmds(const char * line );
void ParseJCmds(const char * line );
void ParseKCmds(const char * line );
void ParseOCmds(const char * line );
void ParseRCmds(const char * line );
void ParseSCmds(const char * line );
void ParseWCmds(const char * line );
void ParseLabel(const char * line );
};
#include "llfrm_varmgr.h"
class CRoot : public CActor
{
public:
CRoot();
virtual ~CRoot();
virtual int InitPlayfield();
virtual void SetNewState( const char * name );
virtual CRoot * CreateStateByName(const char * name) { return 0; }
virtual CActor * FindActor( const char * name);
virtual void InitState(const char *name);
virtual void Action(float delta);
virtual void Draw(llgfx_id id);
virtual bool Message(const char * Type);
virtual bool TranslateMsg(char * Msg, char type);
virtual bool TranslateVar(char * Msg);
const char * GetAlias(char * string);
int Execute( const char * filename, const char *section );
int ExecuteMemory( char * memptr, char * endptr, const char *section );
CRoot * GetStateObject();
static void PostMsg(const char * Msg);
static void HighPriMsg(const char * Msg);
protected:
/*
** Global objects
*/
static queue<CActor> m_global_object_queue;
static CRoot *m_current_state;
static queue<char> m_state_next;
static llqueue_strarray m_aliaslist;
static dequeue<char> m_msg_queue;
private:
void SendMsg(const char * string);
};
/*
** Script controlled Actor logic
** script commands can be one of these types:
*/
typedef enum {
stab_MOVE_TIMED, //
stab_MOVE_VELOCITY,
stab_MOVE_DIRECTION,
stab_OFFSET_TIMED,
stab_OFFSET_VELOCITY,
stab_LABEL,
stab_WAIT,
stab_MSG,
stab_ROTATE_TIMED,
stab_ROTATE_DIR,
stab_SET_POSITION,
stab_SET_GRAVITY,
stab_SET_GRAVITY_PTR,
stab_SET_VIEWANGLE,
stab_SCALE_TIMED,
stab_FADE_TIMED,
stab_CLEAR,
stab_JMP,
stab_KILL,
} actionType;
class CStabAction
{
public:
CStabAction(CActor * actor);
virtual ~CStabAction(){}
virtual void Init() = 0;
virtual CStabAction* Action(float delta) = 0;
virtual actionType GetType() = 0;
bool IsBkgAction() { return m_bkgMove; }
void SetBkgAction(bool val) { m_bkgMove = val; };
protected:
CActor * m_actor;
bool m_bkgMove;
};
/*
** Standard Actor logic
**
*/
class CStabAction_SetPosition : public CStabAction
{
public:
CVec2f m_position;
void Init() { m_actor->m_position = m_position; }
actionType GetType() { return stab_SET_POSITION; }
CStabAction *Action(float delta){ return 0;}
CStabAction_SetPosition( CActor * actor, CVec2f &position )
: CStabAction(actor)
{
m_position = position;
}
};
class CStabAction_SetViewAngle : public CStabAction
{
public:
float m_viewangle;
void Init() { m_actor->SetViewAngleD(m_viewangle); }
actionType GetType() { return stab_SET_VIEWANGLE; }
CStabAction *Action(float delta){ return 0;}
CStabAction_SetViewAngle( CActor * actor, float viewangle )
: CStabAction(actor)
{
m_viewangle = viewangle;
}
};
class CStabAction_Wait : public CStabAction
{
public:
float m_wait;
float m_timer;
void Init() { m_timer = m_wait; }
actionType GetType() { return stab_WAIT; };
CStabAction *Action(float delta){ m_timer -= delta; if( m_timer < 0 ) return 0; else return this;}
CStabAction_Wait( CActor *actor, float wait)
: CStabAction(actor)
{
m_wait = wait;
}
};
class CStabAction_MoveTimed : public CStabAction
{
public:
float m_votime;
CVec2f m_target;
void Init() { m_actor->InitTarget( m_votime, m_target ); m_actor->m_velocity = 1; }
actionType GetType() { return stab_MOVE_TIMED; };
CStabAction* Action(float delta){ if(m_actor->MoveToTarget(delta)) return 0; else return this;}
CStabAction_MoveTimed( CActor *actor, float time, CVec2f &target )
: CStabAction(actor)
{
m_votime = time;
m_target = target;
}
};
class CStabAction_MoveTimedEase : public CStabAction
{
public:
float m_t; // time counter
float m_votime; // total time
CVec2f m_target; // Target
float m_damp; // damping faktor
float m_etime; // Ease time
CVec2f m_direction_sav; // direction vector copy
void Init() { m_actor->InitTarget( m_votime, m_target ); m_direction_sav = m_actor->m_direction; }
actionType GetType() { return stab_MOVE_TIMED; };
CStabAction* Action(float delta){
m_t += delta;
if( m_t >= m_etime ){
m_actor->m_direction -= (m_direction_sav * m_damp) * delta;
}
if(m_actor->MoveToTarget(delta))
return 0;
else
return this;
}
CStabAction_MoveTimedEase( CActor *actor, float time, CVec2f &target, float etime, float damp )
: CStabAction(actor)
{
m_votime = time;
m_target = target;
m_etime = etime;
m_damp = damp;
m_t = 0;
}
};
class CStabAction_MoveTarget : public CStabAction_MoveTimed
{
public:
void Init() { m_actor->InitMove( m_target, m_votime );}
actionType GetType() { return stab_MOVE_VELOCITY; };
CStabAction_MoveTarget(CActor * actor, float velocity, CVec2f &target )
: CStabAction_MoveTimed( actor, velocity, target)
{
}
};
class CStabAction_MoveDirection : public CStabAction_MoveTimed
{
public:
void Init() { CVec2f target = m_actor->m_position + m_target;
m_actor->InitMove( target, m_votime );
};
actionType GetType() { return stab_MOVE_DIRECTION; };
CStabAction* Action(float delta){ m_actor->Move(delta); return this; };
CStabAction_MoveDirection(CActor * actor, float velocity, CVec2f &target )
: CStabAction_MoveTimed( actor, velocity, target)
{
}
};
class CStabAction_OffsetTimed : public CStabAction_MoveTimed
{
public:
void Init() {
CVec2f ipos = m_actor->m_position + m_target;
m_actor->InitTarget( m_votime, ipos );
m_actor->m_velocity = 1;
}
actionType GetType() { return stab_OFFSET_TIMED; };
CStabAction_OffsetTimed( CActor *actor, float time, CVec2f &target )
: CStabAction_MoveTimed(actor,time,target)
{
}
};
class CStabAction_OffsetTarget : public CStabAction_MoveTimed
{
public:
void Init() {
CVec2f ipos = m_actor->m_position + m_target;
m_actor->InitMove( ipos, m_votime );
}
actionType GetType() { return stab_OFFSET_VELOCITY; };
CStabAction_OffsetTarget(CActor * actor, float velocity, CVec2f &target )
: CStabAction_MoveTimed( actor, velocity, target)
{
}
};
class CStabAction_Label : public CStabAction
{
public:
char * m_label;
void Init() {};
actionType GetType() { return stab_LABEL; }
CStabAction* Action(float delta) { return 0; }
CStabAction_Label( CActor * actor, const char * labelname )
: CStabAction(actor)
{
m_label = strdup(labelname);
}
~CStabAction_Label()
{
if( m_label )
free(m_label);
}
};
class CStabAction_Kill : public CStabAction
{
public:
void Init() {};
actionType GetType() { return stab_KILL; }
CStabAction* Action(float delta) { m_actor->m_lifetime = 0.0f; return 0; }
CStabAction_Kill( CActor * actor)
: CStabAction(actor)
{
}
};
//class CStabAction_Clear : public CStabAction
//{
//public:
// void Init() {};
// actionType GetType() { return stab_CLEAR; }
// CStabAction* Action(float delta){ CActor *dsave = m_actor; dsave->ClearScript(); dsave->ClearActions(); return 0; }
//
// CStabAction_Clear( CActor * actor)
// : CStabAction(actor){}
//};
class CStabAction_JMP : public CStabAction_Label
{
public:
actionType GetType() { return stab_JMP; };
CStabAction* Action(float delta)
{
m_actor->m_script.Reset();
while( CStabAction * E = m_actor->m_script.Next() )
{
if( E->GetType() == stab_LABEL )
{
if( 0 == strcmp( m_label, ((CStabAction_Label*)E)->m_label ) )
{
return 0;
}
}
}
return 0;
};
CStabAction_JMP( CActor *actor, char * label )
: CStabAction_Label(actor, label)
{
}
};
class CStabAction_MSG : public CStabAction
{
public:
char * m_msg;
void Init() { }
actionType GetType() { return stab_MSG; };
CStabAction *Action(float delta){ m_actor->SendMsg(m_msg); return 0; }
CStabAction_MSG( CActor *actor, char *msg)
: CStabAction(actor)
{
m_msg = strdup(msg);
}
~CStabAction_MSG()
{
if( m_msg )
free(m_msg);
}
};
class CStabAction_RotateTo : public CStabAction
{
public:
float m_time;
float m_target_angle;
void Init() { m_actor->InitTargetAngleD(m_time,m_target_angle); }
actionType GetType() { return stab_ROTATE_TIMED; };
CStabAction *Action(float delta){ if( m_actor->RotateToTargetAngle(delta)) return 0; else return this; }
CStabAction_RotateTo( CActor *actor, float angle, float time)
: CStabAction(actor)
{
m_target_angle = angle;
m_time = time;
}
};
class CStabAction_RotateDir : public CStabAction_RotateTo
{
public:
float m_time_left;
void Init() { m_time_left = m_time; }
actionType GetType() { return stab_ROTATE_DIR; }
CStabAction *Action(float delta)
{
m_time_left -= delta;
if( m_time_left >= 0 )
{
m_actor->PlusViewAngleD( m_target_angle * delta);
return this;
}
else
return 0;
}
CStabAction_RotateDir( CActor *actor, float angle, float time)
: CStabAction_RotateTo(actor, angle, time)
{
m_target_angle /= m_time;
}
};
class CStabAction_SetGravity : public CStabAction
{
public:
CVec2f m_GravitationOrg; //gravity origin
float m_time;
float m_mass; //masse der gravitation
void Init() { }
actionType GetType() { return stab_SET_GRAVITY; }
CStabAction *Action(float delta)
{
m_time += delta;
float x = (0.5f * GRAVITY)* (m_time*m_time) * m_mass;
m_actor->m_direction += m_GravitationOrg * x;
return this;
}
CStabAction_SetGravity( CActor * actor, CVec2f &gravpos, float mass )
: CStabAction(actor)
{
m_GravitationOrg = gravpos;
m_mass = mass;
m_time = 0;
}
};
class CStabAction_SetGravityPtr : public CStabAction
{
public:
CVec2f *m_GravitationOrg; //gravity origin
float m_mass; //masse der gravitation
void Init() { }
actionType GetType() { return stab_SET_GRAVITY_PTR; }
CStabAction *Action(float delta)
{
CVec2f vector_to_gravity_origin = *m_GravitationOrg - m_actor->m_position;
float d = vector_to_gravity_origin.GetLen();
if( d > 0 ){
float x = (1.0f / d) * m_mass;
m_actor->m_direction += vector_to_gravity_origin * x;
}
return this;
}
CStabAction_SetGravityPtr( CActor * actor, CVec2f *gravpos, float mass )
: CStabAction(actor)
{
m_GravitationOrg = gravpos;
m_mass = mass*0.5f;
}
};
/*
* Vector Scale CActor::m_scale
*/
class CStabAction_ScaleTimed : public CStabAction
{
public:
float m_votime;
CVec2f m_target_scale;
CVec2f m_direction;
void Init() {
if( m_votime <= 0.0f )
{
m_votime = 1.0f;
}
m_direction = m_target_scale - m_actor->m_scale;
m_direction /= m_votime;
}
actionType GetType() { return stab_SCALE_TIMED; };
CStabAction* Action(float delta){
if(m_actor->MoveToTarget(delta,m_actor->m_scale,m_target_scale,m_direction)) return 0; else return this;
}
CStabAction_ScaleTimed( CActor *actor, float time, CVec2f &target )
: CStabAction(actor)
{
m_votime = time;
m_target_scale = target;
}
};
/*
* Float fade (float*) &Actor + offset
*/
class CStabAction_FadeTimed : public CStabAction
{
public:
float m_votime; // zeit f<>r eine fade spanne
CVec2f m_i_fade; // initial wert. m_u = von wert, m_v = zu wert
float m_fade; // aktueller fade, laufvariable
float m_fadeadd; // zeitfaktor
int m_offset; // offset zum float, actor+offset -> zielfloat
bool m_toggle; // wenn true, wird bei endlos loop m_u, m_v umgedreht
bool m_loop; // wenn true, wird endlog geloopoed
int m_repeat; // wenn loop gesetzt ist hier die anzahl, 0=endlosloop
int m_i_repeat; // initialwert
void Init() {
if( m_votime <= 0.0f )
{
m_votime = 1.0f;
}
m_fade = m_i_fade.m_u; // aktueller fade, laufvariable
m_fadeadd = (m_i_fade.m_v-m_i_fade.m_u)/m_votime;
m_repeat = m_i_repeat; // wenn loop gesetzt ist hier die anzahl, 0=endlosloop
}
actionType GetType() { return stab_FADE_TIMED; };
CStabAction* Action(float delta){
m_fade += m_fadeadd * delta;
if( m_fade > m_i_fade.m_v &&
m_fadeadd > 0 ){
m_fade = m_i_fade.m_v; // R<>cksetzen falls <20>ber grenze
}
if( m_fade < m_i_fade.m_v &&
m_fadeadd < 0){
m_fade = m_i_fade.m_v; // R<>cksetzen falls <20>ber grenze
}
TxU8 * P = (TxU8*) m_actor + m_offset;
/*WERT SETZEN*///
*(float*) P = m_fade; /* WERT Gesetzt */
//m_actor->m_blitfx.fixalpha = m_fade;
//
if( m_fade != m_i_fade.m_v ){
return this;
}
if( m_loop == false )
return 0;
// Repeat initialisieren
if( m_toggle ){
m_fadeadd *= -1;
m_fade = m_i_fade.m_v; // Startwert ist Endewert
m_i_fade.m_v = m_i_fade.m_u; //
m_i_fade.m_u = m_fade;
}
m_fade = m_i_fade.m_u; // Startwert, faden geht erst ab repeat loops
// wenn repeatcount gesetzt, diesen pr<70>fen sonst endlosloop
if( m_repeat > 0 ){
m_repeat -- ;
if( m_repeat == 0 ){
//das war der letzte
return 0;
}
}
return this;
}
CStabAction_FadeTimed( CActor *actor, float time, CVec2f &target, int offset, bool toggle, bool loop, int repeat)
: CStabAction(actor)
{
m_i_repeat = repeat+1;
m_offset = offset;
m_votime = time;
m_i_fade = target;
m_toggle = toggle; // wenn true, wird bei endlos loop m_u, m_v umgedreht
m_loop = loop; // wenn true, wird endlog geloopoed
//init
}
};
#endif