diff --git a/doc/files/canvasz.txt b/doc/files/canvasz.txt new file mode 100644 index 0000000..b4bd84b --- /dev/null +++ b/doc/files/canvasz.txt @@ -0,0 +1,8 @@ +#title CanvasZ [RCBasic Doc] +#header function CanvasZ(c_num) + +Returns the Canvas Z Order. + +Note: Canvases with a higher Z order are drawn first and those with lower values will be drawn on top + +#ref SetCanvasZ diff --git a/doc/files/createplanemesh.txt b/doc/files/createplanemesh.txt new file mode 100644 index 0000000..8fd005f --- /dev/null +++ b/doc/files/createplanemesh.txt @@ -0,0 +1,10 @@ +#title CreatePlaneMesh [RCBasic Doc] +#header Function CreatePlaneMesh( w, h, tileCount_w, tileCount_h ) + +Creates a flat plane + +#list +#li w, h - The width and height of the plane +#li tileCount_w, TileCount_h - The number of subdivisions across and down the plane +#/list + diff --git a/doc/files/createspriteanimation.txt b/doc/files/createspriteanimation.txt new file mode 100644 index 0000000..b66598e --- /dev/null +++ b/doc/files/createspriteanimation.txt @@ -0,0 +1,9 @@ +#title CreateSpriteAnimation [RCBasic Doc] +#header Function CreateSpriteAnimation(sprite, anim_length, speed) + +Returns a new sprite animation id + +#list ul +#li anim_length - number of frames in the animation +#li speed - frames per second for the animation +#/list diff --git a/doc/files/createwateractor.txt b/doc/files/createwateractor.txt new file mode 100644 index 0000000..6d4a932 --- /dev/null +++ b/doc/files/createwateractor.txt @@ -0,0 +1,4 @@ +#title CreateWaterActor [RCBasic Doc] +#header function CreateWaterActor( mesh, waveHeight, waveSpeed, waveLength ) + +Creates an actor with water properties set on a base mesh diff --git a/doc/files/getan8scenename.txt b/doc/files/getan8scenename.txt new file mode 100644 index 0000000..5fbe4e1 --- /dev/null +++ b/doc/files/getan8scenename.txt @@ -0,0 +1,4 @@ +#title GetAN8SceneName$ [RCBasic Doc] +#header Function GetAN8SceneName$(an8_project, scene_num) + +Returns the name of a scene in an an8 project diff --git a/doc/files/getnuman8scenes.txt b/doc/files/getnuman8scenes.txt new file mode 100644 index 0000000..bf95065 --- /dev/null +++ b/doc/files/getnuman8scenes.txt @@ -0,0 +1,6 @@ +#title GetNumAN8Scenes [RCBasic Doc] +#header Function GetNumAN8Scenes(an8_project) + +Returns the number of scenes in an an8 project + +#ref LoadAN8 diff --git a/doc/files/getprojectionmatrix.txt b/doc/files/getprojectionmatrix.txt new file mode 100644 index 0000000..52703a6 --- /dev/null +++ b/doc/files/getprojectionmatrix.txt @@ -0,0 +1,12 @@ +#title GetProjectionMatrix [RCBasic Doc] +#header Sub GetProjectionMatrix(matA) + +Gets the camera projection matrix for the active canvas + +Possible values for projection_type +#list ul +#li PROJECTION_TYPE_ORTHOGRAPHIC +#li PROJECTION_TYPE_PERSPECTIVE +#/list + +#ref SetProjectionMatrix diff --git a/doc/files/getspriteanimation.txt b/doc/files/getspriteanimation.txt new file mode 100644 index 0000000..f1b0da7 --- /dev/null +++ b/doc/files/getspriteanimation.txt @@ -0,0 +1,6 @@ +#title GetSpriteAnimation [RCBasic Doc] +#header Function GetSpriteAnimation(sprite) + +Returns the current animation set on a sprite + +#ref SetSpriteAnimation diff --git a/doc/files/getspriteanimationframe.txt b/doc/files/getspriteanimationframe.txt new file mode 100644 index 0000000..35d0222 --- /dev/null +++ b/doc/files/getspriteanimationframe.txt @@ -0,0 +1,4 @@ +#title GetSpriteAnimationFrame [RCBasic Doc] +#header Function GetSpriteAnimationFrame(sprite, animation, anim_frame) + +Returns the frame index in the image source that is set to anim_frame in a sprite's animation diff --git a/doc/files/getspriteanimationlength.txt b/doc/files/getspriteanimationlength.txt new file mode 100644 index 0000000..9e1a1c3 --- /dev/null +++ b/doc/files/getspriteanimationlength.txt @@ -0,0 +1,4 @@ +#title GetSpriteAnimationLength [RCBasic Doc] +#header Function GetSpriteAnimationLength(sprite, animation) + +Returns the number of frames in a sprite animation diff --git a/doc/files/getspriteanimationspeed.txt b/doc/files/getspriteanimationspeed.txt new file mode 100644 index 0000000..9a73237 --- /dev/null +++ b/doc/files/getspriteanimationspeed.txt @@ -0,0 +1,4 @@ +#title GetSpriteAnimationSpeed [RCBasic Doc] +#header Function GetSpriteAnimationSpeed(sprite, animation) + +Returns the frames per second of a sprite animation diff --git a/doc/files/getspritecurrentanimationframe.txt b/doc/files/getspritecurrentanimationframe.txt new file mode 100644 index 0000000..ab019af --- /dev/null +++ b/doc/files/getspritecurrentanimationframe.txt @@ -0,0 +1,4 @@ +#title GetSpriteCurrentAnimationFrame [RCBasic Doc] +#header Function GetSpriteCurrentAnimationFrame(sprite) + +Returns the current frame of a sprite's animation diff --git a/doc/files/getspriteframe.txt b/doc/files/getspriteframe.txt new file mode 100644 index 0000000..18a3529 --- /dev/null +++ b/doc/files/getspriteframe.txt @@ -0,0 +1,4 @@ +#title GetSpriteFrame [RCBasic Doc] +#header Function GetSpriteFrame(sprite) + +Returns the current frame in a sprite's source that it's on in its animation diff --git a/doc/files/getspriteposition.txt b/doc/files/getspriteposition.txt new file mode 100644 index 0000000..f806908 --- /dev/null +++ b/doc/files/getspriteposition.txt @@ -0,0 +1,6 @@ +#title GetSpritePosition [RCBasic Doc] +#header Sub GetSpritePosition(sprite, ByRef x, ByRef y) + +Gets the position of a sprite on the canvas + +#ref TranslateSprite SetSpritePosition diff --git a/doc/files/getspriterotation.txt b/doc/files/getspriterotation.txt new file mode 100644 index 0000000..92b3159 --- /dev/null +++ b/doc/files/getspriterotation.txt @@ -0,0 +1,6 @@ +#title GetSpriteRotation [RCBasic Doc] +#header Function GetSpriteRotation(sprite) + +Returns the angle the sprite is rotated by + +#ref SetSpriteRotation RotateSprite diff --git a/doc/files/getspritescale.txt b/doc/files/getspritescale.txt new file mode 100644 index 0000000..2934309 --- /dev/null +++ b/doc/files/getspritescale.txt @@ -0,0 +1,6 @@ +#title GetSpriteScale [RCBasic Doc] +#header Sub GetSpriteScale(sprite, ByRef x, ByRef y) + +Gets the scale of a sprite + +#ref ScaleSprite SetSpriteScale diff --git a/doc/files/getspritesize.txt b/doc/files/getspritesize.txt new file mode 100644 index 0000000..c841c9a --- /dev/null +++ b/doc/files/getspritesize.txt @@ -0,0 +1,6 @@ +#title GetSpriteSize [RCBasic Doc] +#header Sub GetSpriteSize(sprite, ByRef w, ByRef h) + +Gets the size of a sprite's frames + +#ref CreateSprite diff --git a/doc/files/getspritesource.txt b/doc/files/getspritesource.txt new file mode 100644 index 0000000..58db383 --- /dev/null +++ b/doc/files/getspritesource.txt @@ -0,0 +1,6 @@ +#title GetSpriteSource [RCBasic Doc] +#header Function GetSpriteSource(sprite) + +Returns the source image the sprite renders its frames from + +#ref SetSpriteSource CreateSprite diff --git a/doc/files/getspritetype.txt b/doc/files/getspritetype.txt new file mode 100644 index 0000000..2c789e6 --- /dev/null +++ b/doc/files/getspritetype.txt @@ -0,0 +1,15 @@ +#title GetSpriteType [RCBasic Doc] +#header Function GetSpriteType(sprite) + +Returns the collison body type of a sprite. + +By default, sprites are dynamic when they are created. + +Possible types returned +#list ul +#li SPRITE_TYPE_STATIC +#li SPRITE_TYPE_KINEMATIC +#li SPRITE_TYPE_DYNAMIC +#/list + +#ref SetSpriteType diff --git a/doc/files/getworldtoviewportposition.txt b/doc/files/getworldtoviewportposition.txt new file mode 100644 index 0000000..bca3501 --- /dev/null +++ b/doc/files/getworldtoviewportposition.txt @@ -0,0 +1,4 @@ +#title GetWorldToViewportPosition [RCBasic Doc] +#header Sub GetWorldToViewportPosition(x, y, z, ByRef x, ByRef y) + +Get the 2D coordinates for the given 3D position on the active canvas diff --git a/doc/files/loadan8.txt b/doc/files/loadan8.txt new file mode 100644 index 0000000..634043e --- /dev/null +++ b/doc/files/loadan8.txt @@ -0,0 +1,6 @@ +#title LoadAN8 [RCBasic Doc] +#header Function LoadAN8( an8_file$ ) + +Loads an an8 project and returns an id that can be used in LoadMeshFromAN8() + +#ref LoadMeshFromAN8 diff --git a/doc/files/loadmeshfroman8.txt b/doc/files/loadmeshfroman8.txt new file mode 100644 index 0000000..952142b --- /dev/null +++ b/doc/files/loadmeshfroman8.txt @@ -0,0 +1,8 @@ +#title LoadMeshFromAN8 [RCBasic Doc] +#header Function LoadMeshFromAN8(an8_project, an8_scene$) + +Loads the figures in an anim8or scene as a mesh + +Note: This only loads figures from a scene and it loads meshes not anim8or objects + +#ref LoadAN8 LoadMesh LoadMeshFromArchive diff --git a/doc/files/numspriteanimationloops.txt b/doc/files/numspriteanimationloops.txt new file mode 100644 index 0000000..60b408f --- /dev/null +++ b/doc/files/numspriteanimationloops.txt @@ -0,0 +1,6 @@ +#title NumSpriteAnimationLoops [RCBasic Doc] +#header Function NumSpriteAnimationLoops(sprite) + +Returns the number of animation loops the actor has set + +#ref SetSpriteAnimationLoops SetSpriteAnimation diff --git a/doc/files/preupdate.txt b/doc/files/preupdate.txt new file mode 100644 index 0000000..8c9a5c1 --- /dev/null +++ b/doc/files/preupdate.txt @@ -0,0 +1,8 @@ +#title PreUpdate [RCBasic Doc] +#header Sub PreUpdate( ) + +Processes physics for sprites and actors. + +This is useful if you need to know the post solve positions and rotations prior to drawing them. + +#ref Update diff --git a/doc/files/rotatesprite.txt b/doc/files/rotatesprite.txt new file mode 100644 index 0000000..cdd75cc --- /dev/null +++ b/doc/files/rotatesprite.txt @@ -0,0 +1,6 @@ +#title RotateSprite [RCBasic Doc] +#header Sub RotateSprite(sprite, angle) + +Sets the angle the sprite is rotated by relative to its current rotation + +#ref SetSpriteRotation GetSpriteRotation diff --git a/doc/files/scalesprite.txt b/doc/files/scalesprite.txt new file mode 100644 index 0000000..bf23b2e --- /dev/null +++ b/doc/files/scalesprite.txt @@ -0,0 +1,6 @@ +#title ScaleSprite [RCBasic Doc] +#header Sub ScaleSprite(sprite, x, y) + +Sets the scale of a sprite relative to its current scale + +#ref SetSpriteScale GetSpriteScale diff --git a/doc/files/setcameraprojectionmatrix.txt b/doc/files/setcameraprojectionmatrix.txt new file mode 100644 index 0000000..dd73637 --- /dev/null +++ b/doc/files/setcameraprojectionmatrix.txt @@ -0,0 +1,12 @@ +#title SetCameraProjectionMatrix [RCBasic Doc] +#header Sub SetCameraProjectionMatrix(matA, projection_type) + +Sets the camera projection matrix for the active canvas + +Possible values for projection_type +#list ul +#li PROJECTION_TYPE_ORTHOGRAPHIC +#li PROJECTION_TYPE_PERSPECTIVE +#/list + +#ref GetCameraProjectionMatrix diff --git a/doc/files/setcanvasz.txt b/doc/files/setcanvasz.txt index ec72dd1..77d9ef4 100644 --- a/doc/files/setcanvasz.txt +++ b/doc/files/setcanvasz.txt @@ -3,6 +3,6 @@ Sets the Canvas Z Order. -Note: Canvases with a lower Z order are drawn first and those with higher values will be drawn on top +Note: Canvases with a higher Z order are drawn first and those with lower values will be drawn on top #ref SetCanvasZ diff --git a/doc/files/setprojectionmatrix.txt b/doc/files/setprojectionmatrix.txt new file mode 100644 index 0000000..fe36659 --- /dev/null +++ b/doc/files/setprojectionmatrix.txt @@ -0,0 +1,12 @@ +#title SetProjectionMatrix [RCBasic Doc] +#header Sub SetProjectionMatrix(matA, projection_type) + +Sets the camera projection matrix for the active canvas + +Possible values for projection_type +#list ul +#li PROJECTION_TYPE_ORTHOGRAPHIC +#li PROJECTION_TYPE_PERSPECTIVE +#/list + +#ref GetProjectionMatrix diff --git a/doc/files/setspriteanimation.txt b/doc/files/setspriteanimation.txt new file mode 100644 index 0000000..9a4666d --- /dev/null +++ b/doc/files/setspriteanimation.txt @@ -0,0 +1,8 @@ +#title SetSpriteAnimation [RCBasic Doc] +#header Sub SetSpriteAnimation(sprite, animation) + +Sets the current animation for a sprite + +Note: Once an animation is set, it will automatically start + +#ref GetSpriteAnimation diff --git a/doc/files/setspriteanimationframe.txt b/doc/files/setspriteanimationframe.txt new file mode 100644 index 0000000..825a242 --- /dev/null +++ b/doc/files/setspriteanimationframe.txt @@ -0,0 +1,6 @@ +#title SetSpriteAnimationFrame [RCBasic Doc] +#header Sub SetSpriteAnimationFrame(sprite, animation, anim_frame, frame) + +Sets a frame in a sprite animation + +#ref GetSpriteAnimationFrame diff --git a/doc/files/setspriteanimationlength.txt b/doc/files/setspriteanimationlength.txt new file mode 100644 index 0000000..7af2d54 --- /dev/null +++ b/doc/files/setspriteanimationlength.txt @@ -0,0 +1,6 @@ +#title SetSpriteAnimationLength [RCBasic Doc] +#header Sub SetSpriteAnimationLength(sprite, animation, anim_length) + +Sets the number of frames in a sprite animation + +#ref GetSpriteAnimationLength diff --git a/doc/files/setspriteanimationloops.txt b/doc/files/setspriteanimationloops.txt new file mode 100644 index 0000000..ccbae78 --- /dev/null +++ b/doc/files/setspriteanimationloops.txt @@ -0,0 +1,6 @@ +#title SetSpriteAnimationLoops [RCBasic Doc] +#header Sub SetSpriteAnimationLoops(sprite, num_loops) + +Sets the number of animation loops for the sprite + +#ref NumSpriteAnimationLoops diff --git a/doc/files/setspriteanimationspeed.txt b/doc/files/setspriteanimationspeed.txt new file mode 100644 index 0000000..116738c --- /dev/null +++ b/doc/files/setspriteanimationspeed.txt @@ -0,0 +1,4 @@ +#title SetSpriteAnimationSpeed [RCBasic Doc] +#header Sub SetSpriteAnimationSpeed(sprite, animation, speed) + +Sets the speed in frames per second for a sprite animation diff --git a/doc/files/setspriteframe.txt b/doc/files/setspriteframe.txt new file mode 100644 index 0000000..96633de --- /dev/null +++ b/doc/files/setspriteframe.txt @@ -0,0 +1,4 @@ +#title SetSpriteFrame [RCBasic Doc] +#header Sub SetSpriteFrame(sprite, frame) + +Sets a sprite to a frame in its frame sheet diff --git a/doc/files/setspriterotation.txt b/doc/files/setspriterotation.txt new file mode 100644 index 0000000..1ca2c9f --- /dev/null +++ b/doc/files/setspriterotation.txt @@ -0,0 +1,7 @@ +#title SetSpriteRotation [RCBasic Doc] +#header Sub SetSpriteRotation(sprite, angle) + +Sets the angle the sprite is rotated by + +#ref GetSpriteRotation RotateSprite + diff --git a/doc/files/setspritescale.txt b/doc/files/setspritescale.txt new file mode 100644 index 0000000..6bce8ed --- /dev/null +++ b/doc/files/setspritescale.txt @@ -0,0 +1,6 @@ +#title SetSpriteScale [RCBasic Doc] +#header Sub SetSpriteScale(sprite, x, y) + +Sets the scale of a sprite + +#ref ScaleSprite GetSpriteScale diff --git a/doc/files/setspritesolid.txt b/doc/files/setspritesolid.txt new file mode 100644 index 0000000..bc78604 --- /dev/null +++ b/doc/files/setspritesolid.txt @@ -0,0 +1,7 @@ +#title SetSpriteSolid [RCBasic Doc] +#header Sub SetSpriteSolid(sprite, flag) + +Sets whether a sprite has physics and collision response enabled + +#ref SpriteIsSolid + diff --git a/doc/files/setspritesource.txt b/doc/files/setspritesource.txt new file mode 100644 index 0000000..ab6b476 --- /dev/null +++ b/doc/files/setspritesource.txt @@ -0,0 +1,8 @@ +#title SetSpriteSource [RCBasic Doc] +#header Sub SetSpriteSource(sprite, img) + +Changes the image source for a sprite frame sheet + +Note: This needs to be the same size as the current image source or you will have rendering issues + +#ref GetSpriteSource diff --git a/doc/files/setspritetype.txt b/doc/files/setspritetype.txt new file mode 100644 index 0000000..785e484 --- /dev/null +++ b/doc/files/setspritetype.txt @@ -0,0 +1,12 @@ +#title SetSpriteType [RCBasic Doc] +#header Sub SetSpriteType(sprite, sprite_type) + +Sets the type of collision body a sprite has + +#list ul +#li SPRITE_TYPE_STATIC +#li SPRITE_TYPE_KINEMATIC +#li SPRITE_TYPE_DYNAMIC +#/list + +#ref GetSpriteType diff --git a/doc/files/setspritevisible.txt b/doc/files/setspritevisible.txt new file mode 100644 index 0000000..1c6b8b5 --- /dev/null +++ b/doc/files/setspritevisible.txt @@ -0,0 +1,6 @@ +#title SetSpriteVisible [RCBasic Doc] +#header Sub SetSpriteVisible(sprite, flag) + +Sets whether the sprite is visible + +#ref SpriteIsVisible diff --git a/doc/files/setspritez.txt b/doc/files/setspritez.txt new file mode 100644 index 0000000..89c35e5 --- /dev/null +++ b/doc/files/setspritez.txt @@ -0,0 +1,9 @@ +#title SetSpriteZ [RCBasic Doc] +#header Sub SetSpriteZ(sprite, z) + +Sets the drawing priority for sprites. + +Note: Sprites with a higher Z order are drawn first and those with lower values will be drawn on top + +#ref SpriteZ + diff --git a/doc/files/spriteheight.txt b/doc/files/spriteheight.txt new file mode 100644 index 0000000..38dd2bf --- /dev/null +++ b/doc/files/spriteheight.txt @@ -0,0 +1,7 @@ +#title SpriteHeight [RCBasic Doc] +#header Function SpriteHeight(sprite) + +Returns the frame height of a sprite + +#ref SpriteWidth GetSpriteSize + diff --git a/doc/files/spriteissolid.txt b/doc/files/spriteissolid.txt new file mode 100644 index 0000000..842785f --- /dev/null +++ b/doc/files/spriteissolid.txt @@ -0,0 +1,6 @@ +#title SpriteIsSolid [RCBasic Doc] +#header Function SpriteIsSolid(sprite) + +Returns true if a sprite is has physics and collision response enabled + +#ref SetSpriteSolid diff --git a/doc/files/spriteisvisible.txt b/doc/files/spriteisvisible.txt new file mode 100644 index 0000000..202c2c4 --- /dev/null +++ b/doc/files/spriteisvisible.txt @@ -0,0 +1,6 @@ +#title SpriteIsVisible [RCBasic Doc] +#header Function SpriteIsVisible(sprite) + +Returns whether the sprite is visible + +#ref SetSpriteVisible diff --git a/doc/files/spritewidth.txt b/doc/files/spritewidth.txt new file mode 100644 index 0000000..1971359 --- /dev/null +++ b/doc/files/spritewidth.txt @@ -0,0 +1,6 @@ +#title SpriteWidth [RCBasic Doc] +#header Function SpriteWidth(sprite) + +Returns the frame width of a sprite + +#ref SpriteHeight GetSpriteSize diff --git a/doc/files/spritex.txt b/doc/files/spritex.txt new file mode 100644 index 0000000..15d8cfa --- /dev/null +++ b/doc/files/spritex.txt @@ -0,0 +1,7 @@ +#title SpriteX [RCBasic Doc] +#header Function SpriteX(sprite) + +Returns the X position of a sprite on a canvas + +#ref SpriteY SetSpritePosition GetSpritePosition + diff --git a/doc/files/spritey.txt b/doc/files/spritey.txt new file mode 100644 index 0000000..eec9065 --- /dev/null +++ b/doc/files/spritey.txt @@ -0,0 +1,6 @@ +#title SpriteY [RCBasic Doc] +#header Function SpriteY(sprite) + +Returns the Y position of a sprite on a canvas + +#ref SpriteX SetSpritePosition GetSpritePosition diff --git a/doc/files/spritez.txt b/doc/files/spritez.txt new file mode 100644 index 0000000..b07e400 --- /dev/null +++ b/doc/files/spritez.txt @@ -0,0 +1,8 @@ +#title SpriteZ [RCBasic Doc] +#header Function SpriteZ(sprite) + +Returns the drawing priority for sprites. + +Note: Sprites with a higher Z order are drawn first and those with lower values will be drawn on top + +#ref SetSpriteZ diff --git a/doc/files/textheight.txt b/doc/files/textheight.txt new file mode 100644 index 0000000..1741a1f --- /dev/null +++ b/doc/files/textheight.txt @@ -0,0 +1,7 @@ +#title TextHeight [RCBasic Doc] +#header function TextHeight(txt$) + +The height of text rendered with the active font + +#ref TextWidth GetTextSize + diff --git a/doc/files/textwidth.txt b/doc/files/textwidth.txt new file mode 100644 index 0000000..9865276 --- /dev/null +++ b/doc/files/textwidth.txt @@ -0,0 +1,6 @@ +#title TextWidth [RCBasic Doc] +#header function TextWidth(txt$) + +The width of text rendered with the active font + +#ref TextHeight GetTextSize diff --git a/doc/files/translatesprite.txt b/doc/files/translatesprite.txt new file mode 100644 index 0000000..21b05b6 --- /dev/null +++ b/doc/files/translatesprite.txt @@ -0,0 +1,8 @@ +#title TranslateSprite [RCBasic Doc] +#header Sub TranslateSprite(sprite, x, y) + +Move a sprite relative to its current position + +Note: This function sets the position of a sprite without regards to physics properties so it will not trigger collision detection or collision response. + +#ref SetSpritePosition GetSpritePosition diff --git a/rcbasic_build/rcbasic4_changes.ods b/rcbasic_build/rcbasic4_changes.ods index 071fbc4..5847fcb 100644 Binary files a/rcbasic_build/rcbasic4_changes.ods and b/rcbasic_build/rcbasic4_changes.ods differ diff --git a/rcbasic_build/tokenizer.h b/rcbasic_build/tokenizer.h index 57a2ef0..38ac1e4 100755 --- a/rcbasic_build/tokenizer.h +++ b/rcbasic_build/tokenizer.h @@ -1238,6 +1238,10 @@ string rc_keywordToken(string sline) return "19"; else if(sline.compare("MD2_ANIMATION_BOOM")==0) return "20"; + else if(sline.compare("PROJECTION_TYPE_ORTHOGRAPHIC")==0) + return "0"; + else if(sline.compare("PROJECTION_TYPE_PERSPECTIVE")==0) + return "1"; else if(sline.compare("SPRITE_TYPE_STATIC")==0) return "0"; else if(sline.compare("SPRITE_TYPE_KINEMATIC")==0) diff --git a/rcbasic_runtime/main.cpp b/rcbasic_runtime/main.cpp index 627545b..55f4882 100755 --- a/rcbasic_runtime/main.cpp +++ b/rcbasic_runtime/main.cpp @@ -1577,8 +1577,6 @@ bool rc_free_type(rc_usrId* parent) rc_usrId* p_obj; - uint64_t field_size = 0; - for(uint64_t i = 0; i < dim_size; i++) { p_obj = &parent->uid_value[i]; @@ -1968,7 +1966,7 @@ void for_117(uint64_t nid, int n1, int n2, int n3) //These 3 lines reads the line value passed by the compiler //This line value is the address of the end of the loop - unsigned rcbasic_cmd = segment[current_segment][current_address]; + //unsigned rcbasic_cmd = segment[current_segment][current_address]; current_address++; uint64_t for_end_addr = readInt(); @@ -2273,8 +2271,6 @@ void rc_type_array_copy(rc_usrId* src, rc_usrId* dst) rc_usrId* p_obj; - uint64_t field_size = 0; - rc_usrId* s_obj; //cout << "starting field: " << endl; @@ -3137,7 +3133,7 @@ void obj_usr_init1_185(int u1, int n1) void obj_usr_init2_186(int u1, int n1, int n2) { - uint64_t d[3]; + //uint64_t d[3]; //cout << "obj_usr_init2: u" << u1 << " --dim=[" << d[0] << ", " << d[1] << ", " << d[2] << "]" << endl; usr_object.index = (uint64_t)vm_n[n1].value * vm_u[u1].dim[1] + (uint64_t)vm_n[n2].value; usr_object.obj_ref = &vm_u[u1].var_ref->uid_value[usr_object.index]; @@ -3161,7 +3157,6 @@ bool rc_preset_type(rc_usrId* parent) rc_usrId* p_obj; - uint64_t field_size = 0; for(uint64_t i = 0; i < dim_size; i++) { diff --git a/rcbasic_runtime/rc_func130_cases.h b/rcbasic_runtime/rc_func130_cases.h index 5623dec..1241293 100644 --- a/rcbasic_runtime/rc_func130_cases.h +++ b/rcbasic_runtime/rc_func130_cases.h @@ -1371,7 +1371,7 @@ case FN_ReadInput_ToggleBackspace: //Sub Procedure rc_readInput_ToggleBackspace( READINPUT_TOGGLEBACKSPACE_FLAG ); break; case FN_CreateSprite: //Number Function - rc_push_num(rc_createSprite( CREATESPRITE_IMG )); + rc_push_num(rc_createSprite( CREATESPRITE_IMG, 0, 0 )); break; case FN_DeleteSprite: //Sub Procedure rc_deleteSprite( DELETESPRITE_SPRITE ); diff --git a/rcbasic_runtime/rc_gfx.h b/rcbasic_runtime/rc_gfx.h index f03740d..8b31990 100644 --- a/rcbasic_runtime/rc_gfx.h +++ b/rcbasic_runtime/rc_gfx.h @@ -26,6 +26,7 @@ #include "rc_utf8.h" #include #include "rc_sprite2D.h" +#include "rc_spritelib.h" #include using namespace irr; @@ -913,12 +914,14 @@ int rc_canvasOpen(int w, int h, int vx, int vy, int vw, int vh, int mode, int ca canvas.physics2D.world = NULL; if(canvas_type == RC_CANVAS_TYPE_SPRITE) { - b2Vec2 gravity(0, -9.8); + b2Vec2 gravity(0, 0); canvas.physics2D.world = new b2World(gravity); - canvas.physics2D.timeStep = 1/20.0; //the length of time passed to simulate (seconds) + canvas.physics2D.timeStep = 1/60.0; //the length of time passed to simulate (seconds) canvas.physics2D.velocityIterations = 8; //how strongly to correct velocity canvas.physics2D.positionIterations = 3; //how strongly to correct position canvas.physics2D.enabled = true; + canvas.physics2D.contact_listener = new rc_contactListener_obj(); + canvas.physics2D.world->SetContactListener(canvas.physics2D.contact_listener); } switch(mode) @@ -1309,13 +1312,33 @@ int rc_cloneCanvas(int origin_canvas_id, int mode) return canvas_id; } +void rc_getWorldToViewportPosition(double x, double y, double z, double* vx, double* vy) +{ + if(!VideoDriver) + return; + + if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) + return; + + if(!rc_canvas[rc_active_canvas].texture) + return; + + if(!rc_canvas[rc_active_canvas].camera.camera) + return; + + irr::scene::ISceneCollisionManager* collman = SceneManager->getSceneCollisionManager(); + + irr::core::vector2di vpos = collman->getScreenCoordinatesFrom3DPosition(irr::core::vector3df(x, y, z), rc_canvas[rc_active_canvas].camera.camera); + *vx = vpos.X; + *vy = vpos.Y; +} + + void rc_setClearColor(Uint32 color) { rc_clear_color.set(color); } - - Uint32 rc_rgba(Uint32 r, Uint32 g, Uint32 b, Uint32 a) { irr::video::SColor color(a, r, g, b); @@ -1364,7 +1387,7 @@ Uint32 rc_getPixel(int x, int y) irr::video::SColor * texel = (SColor *)(texels + ((y * pitch) + (x * sizeof(SColor)))); - irr::video::SColor c = texel[0]; + //irr::video::SColor c = texel[0]; texture->unlock(); @@ -2137,18 +2160,6 @@ void rc_readInput_ToggleBackspace(bool flag) } -struct rc_image_obj -{ - irr::video::ITexture* image; - Uint8 alpha = 255; - irr::video::SColor color_mod = irr::video::SColor(255,255,255,255); -}; -irr::core::array rc_image; - -irr::video::E_BLEND_OPERATION rc_blend_mode = irr::video::EBO_ADD; -bool rc_bilinear_filter = false; - - int rc_loadImageEx(std::string img_file, Uint32 color_key = 0, bool use_color_key = true) { rc_image_obj img; @@ -2334,187 +2345,6 @@ int rc_getBlendMode() return (int)rc_blend_mode; } -void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::position2d position, irr::core::position2d rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize) -{ - if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) - return; - - // Store and clear the projection matrix - irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); - driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); - - // Store and clear the view matrix - irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); - driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); - - // Store and clear the world matrix - irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); - driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); - - // Find horizontal and vertical axes after rotation - irr::f32 c = cos(-rotation*irr::core::DEGTORAD); - irr::f32 s = sin(-rotation*irr::core::DEGTORAD); - irr::core::vector2df horizontalAxis(c,s); - irr::core::vector2df verticalAxis(s,-c); - - // First, we'll find the offset of the center and then where the center would be after rotation - irr::core::vector2df centerOffset(position.X+sourceRect.getWidth()/2.0f*scale.X-rotationPoint.X,position.Y+sourceRect.getHeight()/2.0f*scale.Y-rotationPoint.Y); - irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; - center.X += rotationPoint.X; - center.Y += rotationPoint.Y; - - // Now find the corners based off the center - irr::core::vector2df cornerOffset(sourceRect.getWidth()*scale.X/2.0f,sourceRect.getHeight()*scale.Y/2.0f); - verticalAxis *= cornerOffset.Y; - horizontalAxis *= cornerOffset.X; - irr::core::vector2df corner[4]; - corner[0] = center + verticalAxis - horizontalAxis; - corner[1] = center + verticalAxis + horizontalAxis; - corner[2] = center - verticalAxis - horizontalAxis; - corner[3] = center - verticalAxis + horizontalAxis; - - // Find the uv coordinates of the sourceRect - irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); - irr::core::vector2df uvCorner[4]; - uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); - uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); - uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); - uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); - for (irr::s32 i = 0; i < 4; i++) - uvCorner[i] /= textureSize; - - // Vertices for the image - irr::video::S3DVertex vertices[4]; - irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; - - // Convert pixels to world coordinates - //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); - - for (irr::s32 i = 0; i < 4; i++) { - vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); - vertices[i].TCoords = uvCorner[i]; - vertices[i].Color = color; - } - - // Create the material - // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: - // material.BlendOperation = irr::video::EBO_ADD; - irr::video::SMaterial material; - material.Lighting = false; - material.ZWriteEnable = irr::video::EZW_OFF; - material.ZBuffer = false; - material.BackfaceCulling = false; - material.TextureLayer[0].Texture = texture; - material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; - material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); - material.BlendOperation = rc_blend_mode; - //material.BlendOperation = irr::video::EBO_ADD; - - if (useAlphaChannel) - material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; - else - material.MaterialType = irr::video::EMT_SOLID; - - driver->setMaterial(material); - driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); - - // Restore projection, world, and view matrices - driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); - driver->setTransform(irr::video::ETS_VIEW,oldViewMat); - driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); -} - -void draw2DImage2(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::rect destRect, irr::core::position2d rotationPoint, irr::f32 rotation, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize ) -{ - if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) - return; - - // Store and clear the projection matrix - irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); - driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); - - // Store and clear the view matrix - irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); - driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); - - // Store and clear the world matrix - irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); - driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); - - // Find horizontal and vertical axes after rotation - irr::f32 c = cos(-rotation*irr::core::DEGTORAD); - irr::f32 s = sin(-rotation*irr::core::DEGTORAD); - irr::core::vector2df horizontalAxis(c,s); - irr::core::vector2df verticalAxis(s,-c); - - // First, we'll find the offset of the center and then where the center would be after rotation - irr::core::vector2df centerOffset(destRect.UpperLeftCorner.X+destRect.getWidth()/2.0f-rotationPoint.X,destRect.UpperLeftCorner.Y+destRect.getHeight()/2.0f-rotationPoint.Y); - irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; - center.X += rotationPoint.X; - center.Y += rotationPoint.Y; - - // Now find the corners based off the center - irr::core::vector2df cornerOffset(destRect.getWidth()/2.0f,destRect.getHeight()/2.0f); - verticalAxis *= cornerOffset.Y; - horizontalAxis *= cornerOffset.X; - irr::core::vector2df corner[4]; - corner[0] = center + verticalAxis - horizontalAxis; - corner[1] = center + verticalAxis + horizontalAxis; - corner[2] = center - verticalAxis - horizontalAxis; - corner[3] = center - verticalAxis + horizontalAxis; - - // Find the uv coordinates of the sourceRect - irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); - irr::core::vector2df uvCorner[4]; - uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); - uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); - uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); - uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); - for (irr::s32 i = 0; i < 4; i++) - uvCorner[i] /= textureSize; - - // Vertices for the image - irr::video::S3DVertex vertices[4]; - irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; - - // Convert pixels to world coordinates - //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); - - for (irr::s32 i = 0; i < 4; i++) { - vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); - vertices[i].TCoords = uvCorner[i]; - vertices[i].Color = color; - } - - // Create the material - // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: - // material.BlendOperation = irr::video::EBO_ADD; - irr::video::SMaterial material; - material.Lighting = false; - material.ZWriteEnable = irr::video::EZW_OFF; - material.ZBuffer = false; - material.BackfaceCulling = false; - material.TextureLayer[0].Texture = texture; - material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; //TODO: Add option to switch this on/off - material.BlendOperation = rc_blend_mode; - material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); - //material.AntiAliasing = irr::video::EAAM_OFF; - - if (useAlphaChannel) - material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; - else - material.MaterialType = irr::video::EMT_SOLID; - - driver->setMaterial(material); - driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); - - // Restore projection, world, and view matrices - driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); - driver->setTransform(irr::video::ETS_VIEW,oldViewMat); - driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); -} - - void rc_drawImage(int img_id, int x, int y) { if(img_id < 0 || img_id >= rc_image.size()) @@ -3168,196 +2998,6 @@ int rc_canvasClip(int x, int y, int w, int h) -//------------------------------SPRITES------------------------------------------------------- -int rc_createSprite(int img_id) -{ - if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) - return -1; - - if(rc_canvas[rc_active_canvas].type != RC_CANVAS_TYPE_SPRITE) - return -1; - - //std::cout << "debug 1" << std::endl; - - int spr_id = -1; - for(int i = 0; i < rc_sprite.size(); i++) - { - if(!rc_sprite[i].active) - { - spr_id = i; - break; - } - } - - if(spr_id < 0) - { - spr_id = rc_sprite.size(); - rc_sprite2D_obj sprite; - rc_sprite.push_back(sprite); - } - - rc_sprite[spr_id].active = true; - rc_sprite[spr_id].image_id = img_id; - - b2BodyDef sprBodyDef; - sprBodyDef.type = b2_staticBody; - sprBodyDef.position.Set(0, 0); - sprBodyDef.angle = 0; - rc_sprite[spr_id].physics.body = rc_canvas[rc_active_canvas].physics2D.world->CreateBody(&sprBodyDef); - rc_sprite[spr_id].physics_enabled = false; - rc_sprite[spr_id].visible = true; - rc_sprite[spr_id].scale.set(1.0, 1.0); - rc_sprite[spr_id].position.set(0, 0); - rc_sprite[spr_id].alpha = 255; - rc_sprite[spr_id].rotation = 0; - rc_sprite[spr_id].z = 0; - rc_sprite[spr_id].color_mod.set(255,255,255,255); - rc_sprite[spr_id].parent_canvas = rc_active_canvas; - - rc_canvas[rc_active_canvas].sprite.push_back(&rc_sprite[spr_id]); - - return spr_id; -} - -void rc_deleteSprite(int spr_id) -{ - if(spr_id < 0 || spr_id >= rc_sprite.size()) - return; - - if(rc_sprite[spr_id].physics.body) - { - if(rc_sprite[spr_id].parent_canvas >= 0 && rc_sprite[spr_id].parent_canvas < rc_canvas.size()) - { - if(rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world) - rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world->DestroyBody(rc_sprite[spr_id].physics.body); - } - rc_sprite[spr_id].physics.body = NULL; - } - - rc_sprite[spr_id].active = false; - rc_sprite[spr_id].parent_canvas = -1; - - for(int i = 0; i < rc_canvas[rc_active_canvas].sprite.size(); i++) - { - rc_sprite2D_obj* canvas_sprite = rc_canvas[rc_active_canvas].sprite[i]; - rc_sprite2D_obj* global_sprite = &rc_sprite[spr_id]; - if(canvas_sprite == global_sprite) - { - rc_canvas[rc_active_canvas].sprite.erase(i); - break; - } - } -} - -void rc_setSpriteType(int spr_id, int body_type) -{ - if(spr_id < 0 || spr_id >= rc_sprite.size()) - return; - - if(!rc_sprite[spr_id].active) - return; - - rc_sprite[spr_id].physics.body->SetType((b2BodyType) body_type); -} - -void rc_setSpritePosition(int spr_id, double x, double y) -{ - if(spr_id < 0 || spr_id >= rc_sprite.size()) - return; - - if(!rc_sprite[spr_id].active) - return; - - float current_angle = rc_sprite[spr_id].physics.body->GetAngle(); - rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(x, y), current_angle); -} - -//This function is called on each canvas on update -void drawSprites(int canvas_id) -{ - float step = rc_canvas[canvas_id].physics2D.timeStep; - int32 velocityIterations = rc_canvas[canvas_id].physics2D.velocityIterations; - int32 positionIterations = rc_canvas[canvas_id].physics2D.positionIterations; - - if(rc_canvas[canvas_id].physics2D.enabled) - rc_canvas[canvas_id].physics2D.world->Step(step, velocityIterations, positionIterations); - - //Setting the render target to the current canvas. NOTE: I might change this target to a separate sprite layer later. - VideoDriver->setRenderTarget(rc_canvas[canvas_id].texture, false, false); - - - irr::core::dimension2d src_size; - irr::core::rect sourceRect; - - irr::core::position2d position; - - irr::core::position2d rotationPoint; - - irr::f32 rotation = 0; - irr::core::vector2df scale(1.0, 1.0); - bool useAlphaChannel = true; - irr::video::SColor color; - - //irr::core::rect dest( irr::core::vector2d(x, y), irr::core::dimension2d(src_w, src_h));; - - irr::core::vector2df screenSize(rc_canvas[canvas_id].dimension.Width, rc_canvas[canvas_id].dimension.Height); - - int x = 0; - int y = 0; - - b2Vec2 physics_pos; - - irr::f32 RAD_TO_DEG = 180.0/3.141592653589793238463; - - for(int spr_index = 0; spr_index < rc_canvas[canvas_id].sprite.size(); spr_index++) - { - rc_sprite2D_obj* sprite = rc_canvas[canvas_id].sprite[spr_index]; - if(!sprite->visible) - continue; - - int img_id = sprite->image_id; - if(img_id < 0 || img_id >= rc_image.size()) - continue; - - src_size = rc_image[img_id].image->getSize(); - sourceRect = irr::core::rect( irr::core::vector2d(0, 0), src_size); - - physics_pos = sprite->physics.body->GetPosition(); - x = (int)physics_pos.x; - y = (int)physics_pos.y; - position.set(x, y); - - - rotationPoint.set(x + (src_size.Width/2), y + (src_size.Height/2)); - rotation = -1 * (sprite->physics.body->GetAngle() * RAD_TO_DEG); //convert Box2D radians to degrees - - scale.set(sprite->scale.X, sprite->scale.Y); - - color.set(sprite->alpha, - sprite->color_mod.getRed(), - sprite->color_mod.getGreen(), - sprite->color_mod.getBlue()); - - draw2DImage(VideoDriver, rc_image[img_id].image, sourceRect, position, rotationPoint, rotation, scale, useAlphaChannel, color, screenSize); - } - //Must set back to canvas 0 (the backbuffer) before returning - - VideoDriver->setRenderTarget(rc_canvas[0].texture, false, false); -} - -//NOTE TO TBIRD -// 1. Each sprite has a Box2D body. You can look in "rc_sprite2D.h" to see how a sprite is structured. -// 2. A box2D world is setup for each canvas. So a sprite will be attached to the canvas thats active when its created. When that canvas is destroyed, so is the sprite. -// 3. By default, I have the sprite.physics_enabled attribute set to false. I feel like it makes sense to have a user intentionally enable physics since a user may not want physics for every sprite. -// 4. The sprite.visible attribute only determines whether to draw the sprite. The physics simulation will still happen each frame unless physics are disabled. -// 5. Don't change the value of sprite.active. Its used to check whether a sprite exists or not. I have an array of sprites in rc_sprite2D.h and if the active attribute is set to false, I reuse that slot to create a new sprite. If there is no inactive sprites in the array then I add a new sprite index to the array. -// 6. The time step, velocity Iterations, and position iterations are part of the canvas.physics2D attribute. You will need to make functions to allow the user to change those. -// 7. If you want to modify how sprites are rendered then you can just change the drawSprites() function above these notes. - -//-----------------------------END OF SPRITE STUFF------------------------------------------------------------------------------ - - - bool rc_update() { diff --git a/rcbasic_runtime/rc_gfx3D.h b/rcbasic_runtime/rc_gfx3D.h index c469a9b..3c675b0 100644 --- a/rcbasic_runtime/rc_gfx3D.h +++ b/rcbasic_runtime/rc_gfx3D.h @@ -2861,6 +2861,8 @@ double rc_computeActorImpulseDenominator(int actor, double pos_x, double pos_y, { return rc_actor[actor].physics.rigid_body->computeImpulseDenominator(irr::core::vector3df(pos_x, pos_y, pos_z), irr::core::vector3df(normal_x, normal_y, normal_z)); } + + return 0; } double rc_computeActorAngularImpulseDenominator(int actor, double x, double y, double z) @@ -2872,6 +2874,8 @@ double rc_computeActorAngularImpulseDenominator(int actor, double x, double y, d { return rc_actor[actor].physics.rigid_body->computeAngularImpulseDenominator(irr::core::vector3df(x, y, z)); } + + return 0; } void rc_setActorAngularFactor(int actor, double x, double y, double z) @@ -3016,6 +3020,8 @@ int rc_createPointConstraintEx(int actorA, int actorB, double pxA, double pyA, d rc_physics3D.constraints[constraint_id] = p2p; return constraint_id; } + + return -1; } void rc_setPointPivotA(int constraint_id, double x, double y, double z) @@ -3062,6 +3068,8 @@ int rc_createHingeConstraint(int actorA, int frameInA_matrix, bool useReferenceF rc_physics3D.constraints[constraint_id] = hinge; return constraint_id; } + + return -1; } @@ -3088,6 +3096,8 @@ int rc_createHingeConstraintEx(int actorA, int actorB, int frameInA_matrix, int rc_physics3D.constraints[constraint_id] = hinge; return constraint_id; } + + return -1; } int rc_createSlideConstraint(int actorA, int frameInB_matrix, bool useLinearReferenceFrameA) @@ -3110,6 +3120,8 @@ int rc_createSlideConstraint(int actorA, int frameInB_matrix, bool useLinearRefe rc_physics3D.constraints[constraint_id] = slide; return constraint_id; } + + return -1; } int rc_createSlideConstraintEx(int actorA, int actorB, int frameInA_matrix, int frameInB_matrix, bool useLinearReferenceFrameA) @@ -3135,6 +3147,8 @@ int rc_createSlideConstraintEx(int actorA, int actorB, int frameInA_matrix, int rc_physics3D.constraints[constraint_id] = slide; return constraint_id; } + + return -1; } @@ -3159,6 +3173,8 @@ int rc_createConeConstraint(int actorA, int rbAFrame_matrix) rc_physics3D.constraints[constraint_id] = cone; return constraint_id; } + + return -1; } int rc_createConeConstraintEx(int actorA, int actorB, int rbAFrame_matrix, int rbBFrame_matrix) @@ -3184,6 +3200,8 @@ int rc_createConeConstraintEx(int actorA, int actorB, int rbAFrame_matrix, int r rc_physics3D.constraints[constraint_id] = cone; return constraint_id; } + + return -1; } void rc_deleteConstraint(int constraint_id) @@ -5069,7 +5087,7 @@ void rc_setActorFrame(int actor, int frame) void rc_setActorAutoCulling(int actor, int cull_type) { if(actor < 0 || actor >= rc_actor.size()) - return; + return; rc_actor[actor].mesh_node->setAutomaticCulling((irr::scene::E_CULLING_TYPE) cull_type); } @@ -5089,7 +5107,7 @@ int rc_getActorAutoCulling(int actor) void rc_addActorShadow(int actor) { if(actor < 0 || actor >= rc_actor.size()) - return; + return; if(rc_actor[actor].shadow) return; @@ -6699,6 +6717,37 @@ double rc_getCameraNearValue() return rc_canvas[rc_active_canvas].camera.camera->getNearValue(); } +void rc_setCameraProjectionMatrix(int proj_matrix, int proj_type) +{ + if(!(rc_active_canvas > 0 && rc_active_canvas < rc_canvas.size())) + return; + + if(proj_matrix < 0 || proj_matrix >= rc_matrix.size()) + return; + + if(!rc_matrix[proj_matrix].active) + return; + + irr::core::matrix4 irr_mat = rc_convertToIrrMatrix(proj_matrix); + bool isOrtho = (proj_type == RC_PROJECTION_TYPE_ORTHOGRAPHIC); + rc_canvas[rc_active_canvas].camera.camera->setProjectionMatrix(irr_mat, isOrtho); +} + +void rc_getCameraProjectionMatrix(int proj_matrix) +{ + if(!(rc_active_canvas > 0 && rc_active_canvas < rc_canvas.size())) + return; + + if(proj_matrix < 0 || proj_matrix >= rc_matrix.size()) + return; + + if(!rc_matrix[proj_matrix].active) + return; + + irr::core::matrix4 pmat = rc_canvas[rc_active_canvas].camera.camera->getProjectionMatrix(); + rc_convertFromIrrMatrix(pmat, proj_matrix); +} + void rc_addSceneSkyBox(int img_top, int img_bottom, int img_left, int img_right, int img_front, int img_back) { diff --git a/rcbasic_runtime/rc_gfx_core.h b/rcbasic_runtime/rc_gfx_core.h index 2f4f715..f88c8b0 100644 --- a/rcbasic_runtime/rc_gfx_core.h +++ b/rcbasic_runtime/rc_gfx_core.h @@ -283,10 +283,30 @@ struct rc_physicsWorld3D_obj rc_physicsWorld3D_obj rc_physics3D; //Canvases +class rc_contactListener_obj : public b2ContactListener +{ + void BeginContact(b2Contact* contact) + { + rc_sprite2D_obj* spriteA = (rc_sprite2D_obj*) contact->GetFixtureA()->GetBody()->GetUserData().pointer; + + rc_sprite2D_obj* spriteB = (rc_sprite2D_obj*) contact->GetFixtureB()->GetBody()->GetUserData().pointer; + + //std::cout << "sprite[" << spriteA->id << "] collide with sprite[" << spriteB->id << "]" << std::endl; + + } + + void EndContact(b2Contact* contact) + { + + } +}; + struct rc_physicsWorld2D_obj { bool enabled = false; b2World* world; + + rc_contactListener_obj* contact_listener; float timeStep = 1/20.0; //the length of time passed to simulate (seconds) int velocityIterations = 8; //how strongly to correct velocity int positionIterations = 3; //how strongly to correct position @@ -296,6 +316,9 @@ struct rc_physicsWorld2D_obj #define RC_CANVAS_TYPE_3D 1 #define RC_CANVAS_TYPE_SPRITE 2 +#define RC_PROJECTION_TYPE_ORTHOGRAPHIC 0 +#define RC_PROJECTION_TYPE_PERSPECTIVE 1 + struct rc_canvas_obj { irr::video::ITexture* texture; @@ -618,4 +641,199 @@ void printIrrMatrix(irr::core::matrix4 m) std::cout << "[ " << m[i*4] << ", " << m[i*4+1] << ", " << m[i*4+2] << ", " << m[i*4+3] << " ]" << std::endl; } + +struct rc_image_obj +{ + irr::video::ITexture* image; + Uint8 alpha = 255; + irr::video::SColor color_mod = irr::video::SColor(255,255,255,255); +}; +irr::core::array rc_image; + +irr::video::E_BLEND_OPERATION rc_blend_mode = irr::video::EBO_ADD; +bool rc_bilinear_filter = false; + + +void draw2DImage(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::position2d position, irr::core::position2d rotationPoint, irr::f32 rotation, irr::core::vector2df scale, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize) +{ + if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) + return; + + // Store and clear the projection matrix + irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); + driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); + + // Store and clear the view matrix + irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); + driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); + + // Store and clear the world matrix + irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); + driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); + + // Find horizontal and vertical axes after rotation + irr::f32 c = cos(-rotation*irr::core::DEGTORAD); + irr::f32 s = sin(-rotation*irr::core::DEGTORAD); + irr::core::vector2df horizontalAxis(c,s); + irr::core::vector2df verticalAxis(s,-c); + + // First, we'll find the offset of the center and then where the center would be after rotation + irr::core::vector2df centerOffset(position.X+sourceRect.getWidth()/2.0f*scale.X-rotationPoint.X,position.Y+sourceRect.getHeight()/2.0f*scale.Y-rotationPoint.Y); + irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; + center.X += rotationPoint.X; + center.Y += rotationPoint.Y; + + // Now find the corners based off the center + irr::core::vector2df cornerOffset(sourceRect.getWidth()*scale.X/2.0f,sourceRect.getHeight()*scale.Y/2.0f); + verticalAxis *= cornerOffset.Y; + horizontalAxis *= cornerOffset.X; + irr::core::vector2df corner[4]; + corner[0] = center + verticalAxis - horizontalAxis; + corner[1] = center + verticalAxis + horizontalAxis; + corner[2] = center - verticalAxis - horizontalAxis; + corner[3] = center - verticalAxis + horizontalAxis; + + // Find the uv coordinates of the sourceRect + irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); + irr::core::vector2df uvCorner[4]; + uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); + uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); + uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); + uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); + for (irr::s32 i = 0; i < 4; i++) + uvCorner[i] /= textureSize; + + // Vertices for the image + irr::video::S3DVertex vertices[4]; + irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; + + // Convert pixels to world coordinates + //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); + + for (irr::s32 i = 0; i < 4; i++) { + vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); + vertices[i].TCoords = uvCorner[i]; + vertices[i].Color = color; + } + + // Create the material + // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: + // material.BlendOperation = irr::video::EBO_ADD; + irr::video::SMaterial material; + material.Lighting = false; + material.ZWriteEnable = irr::video::EZW_OFF; + material.ZBuffer = false; + material.BackfaceCulling = false; + material.TextureLayer[0].Texture = texture; + material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; + material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); + material.BlendOperation = rc_blend_mode; + //material.BlendOperation = irr::video::EBO_ADD; + + if (useAlphaChannel) + material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; + else + material.MaterialType = irr::video::EMT_SOLID; + + driver->setMaterial(material); + driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); + + // Restore projection, world, and view matrices + driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); + driver->setTransform(irr::video::ETS_VIEW,oldViewMat); + driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); +} + +void draw2DImage2(irr::video::IVideoDriver *driver, irr::video::ITexture* texture, irr::core::rect sourceRect, irr::core::rect destRect, irr::core::position2d rotationPoint, irr::f32 rotation, bool useAlphaChannel, irr::video::SColor color, irr::core::vector2d screenSize ) +{ + if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) + return; + + // Store and clear the projection matrix + irr::core::matrix4 oldProjMat = driver->getTransform(irr::video::ETS_PROJECTION); + driver->setTransform(irr::video::ETS_PROJECTION,irr::core::matrix4()); + + // Store and clear the view matrix + irr::core::matrix4 oldViewMat = driver->getTransform(irr::video::ETS_VIEW); + driver->setTransform(irr::video::ETS_VIEW,irr::core::matrix4()); + + // Store and clear the world matrix + irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD); + driver->setTransform(irr::video::ETS_WORLD,irr::core::matrix4()); + + // Find horizontal and vertical axes after rotation + irr::f32 c = cos(-rotation*irr::core::DEGTORAD); + irr::f32 s = sin(-rotation*irr::core::DEGTORAD); + irr::core::vector2df horizontalAxis(c,s); + irr::core::vector2df verticalAxis(s,-c); + + // First, we'll find the offset of the center and then where the center would be after rotation + irr::core::vector2df centerOffset(destRect.UpperLeftCorner.X+destRect.getWidth()/2.0f-rotationPoint.X,destRect.UpperLeftCorner.Y+destRect.getHeight()/2.0f-rotationPoint.Y); + irr::core::vector2df center = centerOffset.X*horizontalAxis - centerOffset.Y*verticalAxis; + center.X += rotationPoint.X; + center.Y += rotationPoint.Y; + + // Now find the corners based off the center + irr::core::vector2df cornerOffset(destRect.getWidth()/2.0f,destRect.getHeight()/2.0f); + verticalAxis *= cornerOffset.Y; + horizontalAxis *= cornerOffset.X; + irr::core::vector2df corner[4]; + corner[0] = center + verticalAxis - horizontalAxis; + corner[1] = center + verticalAxis + horizontalAxis; + corner[2] = center - verticalAxis - horizontalAxis; + corner[3] = center - verticalAxis + horizontalAxis; + + // Find the uv coordinates of the sourceRect + irr::core::vector2df textureSize(texture->getSize().Width, texture->getSize().Height); + irr::core::vector2df uvCorner[4]; + uvCorner[0] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.UpperLeftCorner.Y); + uvCorner[1] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.UpperLeftCorner.Y); + uvCorner[2] = irr::core::vector2df(sourceRect.UpperLeftCorner.X,sourceRect.LowerRightCorner.Y); + uvCorner[3] = irr::core::vector2df(sourceRect.LowerRightCorner.X,sourceRect.LowerRightCorner.Y); + for (irr::s32 i = 0; i < 4; i++) + uvCorner[i] /= textureSize; + + // Vertices for the image + irr::video::S3DVertex vertices[4]; + irr::u16 indices[6] = { 0, 1, 2, 3 ,2 ,1 }; + + // Convert pixels to world coordinates + //irr::core::vector2df screenSize(rc_canvas[rc_active_canvas].dimension.Width, rc_canvas[rc_active_canvas].dimension.Height); + + for (irr::s32 i = 0; i < 4; i++) { + vertices[i].Pos = irr::core::vector3df(((corner[i].X/screenSize.X)-0.5f)*2.0f,((corner[i].Y/screenSize.Y)-0.5f)*-2.0f,1); + vertices[i].TCoords = uvCorner[i]; + vertices[i].Color = color; + } + + // Create the material + // IMPORTANT: For irrlicht 1.8 and above you MUST ADD THIS LINE: + // material.BlendOperation = irr::video::EBO_ADD; + irr::video::SMaterial material; + material.Lighting = false; + material.ZWriteEnable = irr::video::EZW_OFF; + material.ZBuffer = false; + material.BackfaceCulling = false; + material.TextureLayer[0].Texture = texture; + material.TextureLayer[0].BilinearFilter = rc_bilinear_filter; //TODO: Add option to switch this on/off + material.BlendOperation = rc_blend_mode; + material.MaterialTypeParam = irr::video::pack_textureBlendFunc(irr::video::EBF_SRC_ALPHA, irr::video::EBF_ONE_MINUS_SRC_ALPHA, irr::video::EMFN_MODULATE_1X, irr::video::EAS_TEXTURE | irr::video::EAS_VERTEX_COLOR); + //material.AntiAliasing = irr::video::EAAM_OFF; + + if (useAlphaChannel) + material.MaterialType = irr::video::EMT_ONETEXTURE_BLEND; + else + material.MaterialType = irr::video::EMT_SOLID; + + driver->setMaterial(material); + driver->drawIndexedTriangleList(&vertices[0],4,&indices[0],2); + + // Restore projection, world, and view matrices + driver->setTransform(irr::video::ETS_PROJECTION,oldProjMat); + driver->setTransform(irr::video::ETS_VIEW,oldViewMat); + driver->setTransform(irr::video::ETS_WORLD,oldWorldMat); +} + + + #endif // RC_GFX_CORE_H_INCLUDED diff --git a/rcbasic_runtime/rc_matrix.h b/rcbasic_runtime/rc_matrix.h index 675c93d..d633aab 100755 --- a/rcbasic_runtime/rc_matrix.h +++ b/rcbasic_runtime/rc_matrix.h @@ -901,7 +901,6 @@ bool rc_scalarMatrixColumns(uint32_t mA, uint32_t mB, uint32_t c, uint32_t num_c rc_copyMatrix(mA, mB); int row_offset = 0; - int b_offset = 0; for(int row = 0; row < rc_matrix[mB].r; row++) { row_offset = row * rc_matrix[mB].c; diff --git a/rcbasic_runtime/rc_sprite2D.h b/rcbasic_runtime/rc_sprite2D.h index 6a013dc..bffaa0c 100644 --- a/rcbasic_runtime/rc_sprite2D.h +++ b/rcbasic_runtime/rc_sprite2D.h @@ -7,24 +7,52 @@ struct rc_sprite2D_physics_obj { b2Body* body; + b2Fixture* fixture; + b2Shape* shape; + + int offset_x; + int offset_y; +}; + +struct rc_sprite2D_animation_obj +{ + irr::core::array frames; + + int num_frames; + + int current_frame; + + double fps; + double frame_start_time; + double frame_swap_time; }; struct rc_sprite2D_obj { + int id; //This is needed to reference this sprite in the contact listener bool active = false; int image_id; - irr::core::vector2d position; - irr::f64 rotation; + int sheet_numFrames; + int frames_per_row; + irr::core::vector2d scale; + irr::core::dimension2d frame_size; + bool visible = true; Uint8 alpha; irr::video::SColor color_mod; - bool physics_enabled = false; + bool isSolid = false; rc_sprite2D_physics_obj physics; + int current_animation; + int num_animation_loops; + int current_animation_loop; + bool isPlaying; + irr::core::array animation; + int parent_canvas = -1; double z; diff --git a/rcbasic_runtime/rc_spritelib.h b/rcbasic_runtime/rc_spritelib.h new file mode 100644 index 0000000..cad66c6 --- /dev/null +++ b/rcbasic_runtime/rc_spritelib.h @@ -0,0 +1,864 @@ +#ifndef RC_SPRITELIB_H_INCLUDED +#define RC_SPRITELIB_H_INCLUDED + +#ifdef RC_ANDROID + #include "SDL.h" +#else + #include +#endif // _IRR_ANDROID_PLATFORM_ + +#include "rc_sprite2D.h" +#include "rc_gfx_core.h" + +#define RC_SPRITE_BASE_ANIMATION 0 + +int rc_createSpriteAnimation(int spr_id, int anim_length, double fps) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + if(anim_length <= 0) + anim_length = 1; + + rc_sprite2D_animation_obj animation; + animation.current_frame = 0; + animation.fps = fps; + animation.frame_swap_time = 1000/fps; + animation.num_frames = anim_length; + for(int i = 0; i < anim_length; i++) + animation.frames.push_back(0); + + int animation_id = rc_sprite[spr_id].animation.size(); + rc_sprite[spr_id].animation.push_back(animation); + + return animation_id; +} + +void rc_setSpriteFrame(int spr_id, int frame) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(frame < 0 || frame >= rc_sprite[spr_id].sheet_numFrames) + return; + + rc_sprite[spr_id].current_animation = RC_SPRITE_BASE_ANIMATION; + rc_sprite[spr_id].animation[RC_SPRITE_BASE_ANIMATION].current_frame = 0; + rc_sprite[spr_id].animation[RC_SPRITE_BASE_ANIMATION].frames[0] = frame; +} + +int rc_getSpriteFrame(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + int current_animation = rc_sprite[spr_id].current_animation; + int current_frame = rc_sprite[spr_id].animation[current_animation].current_frame; + return rc_sprite[spr_id].animation[current_animation].frames[current_frame]; +} + +void rc_setSpriteAnimationFrame(int spr_id, int spr_animation, int anim_frame, int frame) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(anim_frame < 0 || anim_frame >= rc_sprite[spr_id].animation[spr_animation].num_frames) + return; + + if(frame < 0 || frame >= rc_sprite[spr_id].sheet_numFrames) + return; + + rc_sprite[spr_id].animation[spr_animation].frames[anim_frame] = frame; +} + +int rc_getSpriteAnimationFrame(int spr_id, int spr_animation, int anim_frame) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + if(anim_frame < 0 || anim_frame >= rc_sprite[spr_id].animation[spr_animation].num_frames) + return -1; + + return rc_sprite[spr_id].animation[spr_animation].frames[anim_frame]; +} + + +void rc_setSpriteAnimationLength(int spr_id, int animation, int num_frames) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + // I intentionally checked for less than or equal to 0 because 0 is the base animation and should not be changed + if(animation <= 0 || animation >= rc_sprite[spr_id].animation.size()) + return; + + if(num_frames <= 0) + num_frames = 1; + + if(num_frames > rc_sprite[spr_id].animation[animation].num_frames) + { + for(int i = rc_sprite[spr_id].animation[animation].num_frames; i < rc_sprite[spr_id].animation[animation].frames.size(); i++) + rc_sprite[spr_id].animation[animation].frames[i] = 0; + } + + rc_sprite[spr_id].animation[animation].num_frames = num_frames; + if(num_frames > rc_sprite[spr_id].animation[animation].frames.size()) + { + while(num_frames > rc_sprite[spr_id].animation[animation].frames.size()) + rc_sprite[spr_id].animation[animation].frames.push_back(0); + } + + if(num_frames < rc_sprite[spr_id].animation[animation].frames.size()) + { + if(rc_sprite[spr_id].animation[animation].current_frame >= num_frames) + rc_sprite[spr_id].animation[animation].current_frame = num_frames - 1; + } +} + +int rc_getSpriteAnimationLength(int spr_id, int animation) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + if(animation < 0 || animation >= rc_sprite[spr_id].animation.size()) + return 0; + + return rc_sprite[spr_id].animation[animation].num_frames; +} + +void rc_setSpriteAnimationSpeed(int spr_id, int animation, double fps) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(animation < 0 || animation >= rc_sprite[spr_id].animation.size()) + return; + + rc_sprite[spr_id].animation[animation].fps = fps; + rc_sprite[spr_id].animation[animation].frame_swap_time = 1000/fps; +} + +double rc_getSpriteAnimationSpeed(int spr_id, int animation) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + if(animation < 0 || animation >= rc_sprite[spr_id].animation.size()) + return 0; + + return rc_sprite[spr_id].animation[animation].fps; +} + +void rc_setSpriteAnimation(int spr_id, int animation) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(animation < 0 || animation >= rc_sprite[spr_id].animation.size()) + return; + + rc_sprite[spr_id].current_animation = animation; + rc_sprite[spr_id].animation[animation].current_frame = 0; + rc_sprite[spr_id].isPlaying = true; + rc_sprite[spr_id].animation[animation].frame_start_time = SDL_GetTicks(); +} + +int rc_getSpriteAnimation(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + return rc_sprite[spr_id].current_animation; +} + +int rc_getSpriteCurrentAnimationFrame(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + int current_animation = rc_sprite[spr_id].current_animation; + return rc_sprite[spr_id].animation[current_animation].current_frame; +} + +void rc_setSpriteAnimationLoops(int spr_id, int num_loops) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].num_animation_loops = num_loops; +} + +int rc_numSpriteAnimationLoops(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return rc_sprite[spr_id].num_animation_loops; +} + +//------------------------------SPRITES------------------------------------------------------- +//Larger z gets drawn first +void sortSpriteZ(int canvas_id) +{ + if(canvas_id < 0 || canvas_id >= rc_canvas.size()) + return; + + if(!rc_canvas[canvas_id].texture) + return; + + for(int i = 0; i < rc_canvas[canvas_id].sprite.size(); i++) + { + rc_sprite2D_obj* spriteA = rc_canvas[canvas_id].sprite[i]; + + for(int j = i+1; j < rc_canvas[canvas_id].sprite.size(); j++) + { + rc_sprite2D_obj* spriteB = rc_canvas[canvas_id].sprite[j]; + + if(spriteB->z > spriteA->z) + { + rc_canvas[canvas_id].sprite[j] = NULL; + rc_canvas[canvas_id].sprite.erase(j); + rc_canvas[canvas_id].sprite.insert(spriteB, i); + } + } + } +} + + +int rc_createSprite(int img_id, double w, double h) +{ + if(rc_active_canvas < 0 || rc_active_canvas >= rc_canvas.size()) + return -1; + + if(rc_canvas[rc_active_canvas].type != RC_CANVAS_TYPE_SPRITE) + return -1; + + //std::cout << "debug 1" << std::endl; + + int spr_id = -1; + for(int i = 0; i < rc_sprite.size(); i++) + { + if(!rc_sprite[i].active) + { + spr_id = i; + break; + } + } + + if(spr_id < 0) + { + spr_id = rc_sprite.size(); + rc_sprite2D_obj sprite; + rc_sprite.push_back(sprite); + } + + rc_sprite[spr_id].active = true; + rc_sprite[spr_id].id = spr_id; + rc_sprite[spr_id].image_id = img_id; + rc_sprite[spr_id].frame_size.set(w, h); + + if(img_id >= 0 && img_id < rc_image.size()) + { + if(rc_image[img_id].image) + { + int img_w = rc_image[img_id].image->getSize().Width; + int img_h = rc_image[img_id].image->getSize().Height; + + rc_sprite[spr_id].frames_per_row = (int)(img_w / w); + rc_sprite[spr_id].sheet_numFrames = ((int)(img_h / h)) * rc_sprite[spr_id].frames_per_row; + } + else + rc_sprite[spr_id].image_id = -1; + } + else + rc_sprite[spr_id].image_id = -1; + + b2BodyDef sprBodyDef; + sprBodyDef.type = b2_dynamicBody; + sprBodyDef.position.Set(0, 0); + sprBodyDef.angle = 0; + sprBodyDef.userData.pointer = (uintptr_t)&rc_sprite[spr_id]; + rc_sprite[spr_id].physics.body = rc_canvas[rc_active_canvas].physics2D.world->CreateBody(&sprBodyDef); + + b2FixtureDef sprFixtureDef; + rc_sprite[spr_id].physics.shape = new b2PolygonShape(); + b2PolygonShape* fix_shape = (b2PolygonShape*)rc_sprite[spr_id].physics.shape; + fix_shape->SetAsBox(w/2, h/2); + sprFixtureDef.shape = rc_sprite[spr_id].physics.shape; + sprFixtureDef.isSensor = true; + sprFixtureDef.density = 1; + rc_sprite[spr_id].physics.fixture = rc_sprite[spr_id].physics.body->CreateFixture(&sprFixtureDef); + + rc_sprite[spr_id].physics.offset_x = 0; + rc_sprite[spr_id].physics.offset_y = 0; + rc_sprite[spr_id].isSolid = false; + + if(rc_sprite[spr_id].image_id < 0) + rc_sprite[spr_id].visible =false; + else + rc_sprite[spr_id].visible = true; + + rc_sprite[spr_id].scale.set(1.0, 1.0); + rc_sprite[spr_id].alpha = 255; + rc_sprite[spr_id].z = 0; + rc_sprite[spr_id].color_mod.set(255,255,255,255); + rc_sprite[spr_id].parent_canvas = rc_active_canvas; + + rc_sprite[spr_id].current_animation = RC_SPRITE_BASE_ANIMATION; + rc_sprite[spr_id].num_animation_loops = 0; + rc_sprite[spr_id].current_animation_loop = 0; + rc_sprite[spr_id].isPlaying = false; + rc_sprite[spr_id].animation.clear(); + rc_createSpriteAnimation(spr_id, 1, 0); + + rc_canvas[rc_active_canvas].sprite.push_back(&rc_sprite[spr_id]); + + sortSpriteZ(rc_active_canvas); + + return spr_id; +} + +void rc_deleteSprite(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(rc_sprite[spr_id].physics.body) + { + if(rc_sprite[spr_id].parent_canvas >= 0 && rc_sprite[spr_id].parent_canvas < rc_canvas.size()) + { + if(rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world) + rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world->DestroyBody(rc_sprite[spr_id].physics.body); + } + rc_sprite[spr_id].physics.body = NULL; + } + + rc_sprite[spr_id].active = false; + rc_sprite[spr_id].parent_canvas = -1; + rc_sprite[spr_id].animation.clear(); + + for(int i = 0; i < rc_canvas[rc_active_canvas].sprite.size(); i++) + { + rc_sprite2D_obj* canvas_sprite = rc_canvas[rc_active_canvas].sprite[i]; + rc_sprite2D_obj* global_sprite = &rc_sprite[spr_id]; + if(canvas_sprite == global_sprite) + { + rc_canvas[rc_active_canvas].sprite.erase(i); + break; + } + } +} + +void rc_setSpriteSource(int spr_id, int img_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(img_id < 0) + { + rc_sprite[spr_id].image_id = -1; + return; + } + + if(img_id >= rc_image.size()) + return; + + if(!rc_image[img_id].image) + return; + + rc_sprite[spr_id].image_id = img_id; +} + +int rc_getSpriteSource(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + return rc_sprite[spr_id].image_id; +} + + +void rc_setSpriteType(int spr_id, int body_type) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].physics.body->SetType((b2BodyType) body_type); +} + +int rc_getSpriteType(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return -1; + + if(!rc_sprite[spr_id].active) + return -1; + + return (int)rc_sprite[spr_id].physics.body->GetType(); +} + +void rc_setSpriteSolid(int spr_id, bool flag) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].isSolid = flag; + rc_sprite[spr_id].physics.fixture->SetSensor(!flag); +} + +bool rc_spriteIsSolid(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return false; + + if(!rc_sprite[spr_id].active) + return false; + + return rc_sprite[spr_id].isSolid; +} + +void rc_setSpritePosition(int spr_id, double x, double y) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + float current_angle = rc_sprite[spr_id].physics.body->GetAngle(); + rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(x, y), current_angle); +} + +void rc_translateSprite(int spr_id, double x, double y) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + float current_angle = rc_sprite[spr_id].physics.body->GetAngle(); + double spr_x = rc_sprite[spr_id].physics.body->GetPosition().x + x; + double spr_y = rc_sprite[spr_id].physics.body->GetPosition().y + y; + rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(spr_x, spr_y), current_angle); +} + +void rc_getSpritePosition(int spr_id, double* x, double* y) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + *x = (double)rc_sprite[spr_id].physics.body->GetPosition().x; + *y = (double)rc_sprite[spr_id].physics.body->GetPosition().y; +} + +double rc_spriteX(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return (double)rc_sprite[spr_id].physics.body->GetPosition().x; +} + +double rc_spriteY(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return (double)rc_sprite[spr_id].physics.body->GetPosition().y; +} + +void rc_setSpriteRotation(int spr_id, double angle) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].physics.body->SetTransform(rc_sprite[spr_id].physics.body->GetPosition(), angle); +} + +void rc_rotateSprite(int spr_id, double angle) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + float new_angle = rc_sprite[spr_id].physics.body->GetAngle() + angle; + rc_sprite[spr_id].physics.body->SetTransform(rc_sprite[spr_id].physics.body->GetPosition(), new_angle); +} + +double rc_getSpriteRotation(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return rc_sprite[spr_id].physics.body->GetAngle(); +} + +void rc_setSpriteScale(int spr_id, double x, double y) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].scale.set(x, y); + + if(rc_sprite[spr_id].isSolid) + { + if(rc_sprite[spr_id].physics.fixture) + { + b2FixtureDef fixdef; + fixdef.density = rc_sprite[spr_id].physics.fixture->GetDensity(); + fixdef.friction = rc_sprite[spr_id].physics.fixture->GetFriction(); + fixdef.restitution = rc_sprite[spr_id].physics.fixture->GetRestitution(); + fixdef.restitutionThreshold = rc_sprite[spr_id].physics.fixture->GetRestitutionThreshold(); + fixdef.shape = rc_sprite[spr_id].physics.shape; + fixdef.isSensor = !(rc_sprite[spr_id].isSolid); + + switch(fixdef.shape->GetType()) + { + case b2Shape::e_circle: + { + b2CircleShape* shape = (b2CircleShape*)fixdef.shape; + shape->m_radius = (x+y)/2; + } + break; + + case b2Shape::e_polygon: + { + b2PolygonShape* shape = (b2PolygonShape*)fixdef.shape; + for(int i = 0; i < shape->m_count; i++) + { + shape->m_vertices[i].x *= x; + shape->m_vertices[i].y *= y; + } + } + break; + + case b2Shape::e_chain: + { + b2ChainShape* shape = (b2ChainShape*)fixdef.shape; + for(int i = 0; i < shape->m_count; i++) + { + shape->m_vertices[i].x *= x; + shape->m_vertices[i].y *= y; + } + } + break; + + case b2Shape::e_edge: + { + b2EdgeShape* shape = (b2EdgeShape*)fixdef.shape; + + shape->m_vertex0.x *= x; + shape->m_vertex0.y *= y; + + shape->m_vertex1.x *= x; + shape->m_vertex1.y *= y; + + shape->m_vertex2.x *= x; + shape->m_vertex2.y *= y; + + shape->m_vertex3.x *= x; + shape->m_vertex3.y *= y; + } + break; + } + + rc_sprite[spr_id].physics.body->DestroyFixture(rc_sprite[spr_id].physics.fixture); + rc_sprite[spr_id].physics.fixture = rc_sprite[spr_id].physics.body->CreateFixture(&fixdef); + } + } +} + +void rc_scaleSprite(int spr_id, double x, double y) +{ + double scale_x = rc_sprite[spr_id].scale.X * x; + double scale_y = rc_sprite[spr_id].scale.Y * y; + rc_setSpriteScale(spr_id, scale_x, scale_y); +} + +double rc_spriteWidth(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return rc_sprite[spr_id].frame_size.Width; +} + +double rc_spriteHeight(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return rc_sprite[spr_id].frame_size.Height; +} + +void rc_getSpriteSize(int spr_id, double* w, double* h) +{ + *w = 0; + *h = 0; + + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + *w = rc_sprite[spr_id].frame_size.Width; + *h = rc_sprite[spr_id].frame_size.Height; +} + +void rc_setSpriteZ(int spr_id, double z) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + rc_sprite[spr_id].z = z; + sortSpriteZ(rc_sprite[spr_id].parent_canvas); +} + +double rc_spriteZ(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return 0; + + if(!rc_sprite[spr_id].active) + return 0; + + return rc_sprite[spr_id].z; +} + +void rc_setSpriteVisible(int spr_id, bool flag) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return; + + if(!rc_sprite[spr_id].active) + return; + + if(rc_sprite[spr_id].image_id) + rc_sprite[spr_id].visible = flag; + else + rc_sprite[spr_id].visible = false; +} + +bool rc_spriteIsVisible(int spr_id) +{ + if(spr_id < 0 || spr_id >= rc_sprite.size()) + return false; + + if(!rc_sprite[spr_id].active) + return false; + + return rc_sprite[spr_id].visible; +} + + + +//-----------------------------------PHYSICS---------------------------------------------------------------------------------- + + + +//This function is called on each canvas on update +void drawSprites(int canvas_id) +{ + float step = rc_canvas[canvas_id].physics2D.timeStep; + int32 velocityIterations = rc_canvas[canvas_id].physics2D.velocityIterations; + int32 positionIterations = rc_canvas[canvas_id].physics2D.positionIterations; + + if(rc_canvas[canvas_id].physics2D.enabled) + rc_canvas[canvas_id].physics2D.world->Step(step, velocityIterations, positionIterations); + + //Setting the render target to the current canvas. NOTE: I might change this target to a separate sprite layer later. + VideoDriver->setRenderTarget(rc_canvas[canvas_id].texture, true, false); + + + irr::core::dimension2d src_size; + irr::core::rect sourceRect; + + irr::core::position2d position; + + irr::core::position2d rotationPoint; + + irr::f32 rotation = 0; + irr::core::vector2df scale(1.0, 1.0); + bool useAlphaChannel = true; + irr::video::SColor color; + + //irr::core::rect dest( irr::core::vector2d(x, y), irr::core::dimension2d(src_w, src_h));; + + irr::core::vector2df screenSize(rc_canvas[canvas_id].dimension.Width, rc_canvas[canvas_id].dimension.Height); + + int x = 0; + int y = 0; + + b2Vec2 physics_pos; + + irr::f32 RAD_TO_DEG = 180.0/3.141592653589793238463; + + double spr_timer = SDL_GetTicks(); + + for(int spr_index = 0; spr_index < rc_canvas[canvas_id].sprite.size(); spr_index++) + { + rc_sprite2D_obj* sprite = rc_canvas[canvas_id].sprite[spr_index]; + if(!sprite->visible) + continue; + + int img_id = sprite->image_id; + if(img_id < 0 || img_id >= rc_image.size()) + continue; + + //src_size = rc_image[img_id].image->getSize(); + int current_animation = sprite->current_animation; + if((spr_timer - sprite->animation[current_animation].frame_start_time) >= sprite->animation[current_animation].frame_swap_time) + { + sprite->animation[current_animation].current_frame++; + + if(sprite->animation[current_animation].current_frame >= sprite->animation[current_animation].num_frames) + { + sprite->animation[current_animation].current_frame = 0; + sprite->current_animation_loop++; + + if(sprite->current_animation_loop >= sprite->num_animation_loops) + { + if(sprite->num_animation_loops < 0) + sprite->isPlaying = true; + else + sprite->isPlaying = false; + sprite->current_animation_loop = 0; + } + } + + if(!sprite->isPlaying) + sprite->animation[current_animation].current_frame = 0; + + sprite->animation[current_animation].frame_start_time = spr_timer; + } + + int current_animation_frame = sprite->animation[current_animation].current_frame; + + int frame_x = (int)(sprite->animation[current_animation].frames[current_animation_frame]%sprite->frames_per_row)*sprite->frame_size.Width; + int frame_y = (int)(sprite->animation[current_animation].frames[current_animation_frame]/sprite->frames_per_row)*sprite->frame_size.Height; + irr::core::vector2d frame_pos(frame_x, frame_y); + src_size = sprite->frame_size; + sourceRect = irr::core::rect( frame_pos, src_size); + //sourceRect = irr::core::rect( irr::core::vector2d(0, 0), src_size); + + physics_pos = sprite->physics.body->GetPosition(); + x = (int)physics_pos.x; + y = (int)physics_pos.y; + position.set(x, y); + + + rotationPoint.set(x + (src_size.Width/2), y + (src_size.Height/2)); //TODO: need to account for offset once that is implemented + rotation = -1 * (sprite->physics.body->GetAngle() * RAD_TO_DEG); //convert Box2D radians to degrees + + scale.set(sprite->scale.X, sprite->scale.Y); + + color.set(sprite->alpha, + sprite->color_mod.getRed(), + sprite->color_mod.getGreen(), + sprite->color_mod.getBlue()); + + //I don't want to draw an image that doesn't exists. Thats just crazy. + draw2DImage(VideoDriver, rc_image[img_id].image, sourceRect, position, rotationPoint, rotation, scale, useAlphaChannel, color, screenSize); + } + //Must set back to canvas 0 (the backbuffer) before returning + + VideoDriver->setRenderTarget(rc_canvas[0].texture, false, false); +} + +//NOTE TO TBIRD +// 1. Each sprite has a Box2D body. You can look in "rc_sprite2D.h" to see how a sprite is structured. +// 2. A box2D world is setup for each canvas. So a sprite will be attached to the canvas thats active when its created. When that canvas is destroyed, so is the sprite. +// 3. By default, I have the sprite.physics_enabled attribute set to false. I feel like it makes sense to have a user intentionally enable physics since a user may not want physics for every sprite. +// 4. The sprite.visible attribute only determines whether to draw the sprite. The physics simulation will still happen each frame unless physics are disabled. +// 5. Don't change the value of sprite.active. Its used to check whether a sprite exists or not. I have an array of sprites in rc_sprite2D.h and if the active attribute is set to false, I reuse that slot to create a new sprite. If there is no inactive sprites in the array then I add a new sprite index to the array. +// 6. The time step, velocity Iterations, and position iterations are part of the canvas.physics2D attribute. You will need to make functions to allow the user to change those. +// 7. If you want to modify how sprites are rendered then you can just change the drawSprites() function above these notes. + +//-----------------------------END OF SPRITE STUFF------------------------------------------------------------------------------ + +#endif // RC_SPRITELIB_H_INCLUDED