![]() |
|
![]() www.icons8.com |
This tutorial shows how sprites can be manipulated and explains the different
styles. This is the same like manipulating the character display.
It is also shown, how the Commodore keyboard input can be
captured in the script:
Pressing the 0 to 4 button changes the displaymode.
This is the "Tutorial07" included in the Tutorial-Download.
The main point of this "magic" is the OnSprite() function, which is calles
for every sprite, that is to be displayed.
When this function is not present or just returns true, a default manipulation
is applied as seen at the start of the video.
The spriteInfo gives us detailed information about the sprite (see SpriteInfo). In this case only the spriteIndex is needed to distinguish between our two sprited; in some cases we maybe also need the graphics address or the color (e.g. when sprite multiplexing is done).
Our first sprite just gets a static view mode. The second will depend on the
variable voxelMode, which is set in the OnKeyboard() function and so
controlled by the user.
Also the second sprite gets a special depth map, which has "ghost" shape. The
depth-map defines the depth factor for each pixel of the sprite (or character).
A pixel with depth of 0.5 is just half as depth as a pixel with factor 1.0. The
back and front side of a sprite (or character) can have different depth-map, so
the shape of the sprite can be different for front and back-side.
const int MapEmptyId = 1;
grid<float> mapEmpty = { {0.0, 0.0},
{0.0, 0.0} };
const int MapGhostId = 2;
grid<float> mapGhost = { // a 24x21 depth-map
.... CODE REMOVED (see
Tutorial-Download) ...
};
const int startProgramTimerId = 1;
float spriteRotationY = 0.0;
float spriteRotationYDir = -1.0;
float spriteRotationX = 0.0;
float spriteRotationXDir = -1.0;
bool enableSpriteManipulation = false;
Voxel voxelMode = Voxel::HardEdge;
// This is called, when we loaded the script-file
void OnLoad(bool reloaded)
{
string scriptPath = APP.GetScriptPath();
APP.ClearDepthMaps(); // Clear all loaded depth maps
APP.ClearModels(); // Clear all loaded model
// Set the view mode to the new 3D
APP.ViewMode = ViewMode::Ext3D;
// Set the ambient light color and brigtness
APP.SetAmbientLight(0.3, 0.3, 0.3);
// Set the direction of the light (from the middle off the
scene (x), from top to bottom (y) and back to forth (z))
APP.SetLightDir(0.0, -1.0, +1.0);
// Position the scene, so we have the top/left in the middle
of the screen
E3D.SetScenePosition(0.44, -0.20, +0.01);
// Rotate the scene a little bit, so we can see the 3D effect
E3D.SetSceneOrientation(-25.0, -28.0, 0.0, 0.0); // yaw,
pitch, roll in degree, speed
if (!reloaded)
{
// Load our "game"
APP.Load(scriptPath + "Sprites.prg",
0);
SetTimer(startProgramTimerId, 120,
false);
}
}
bool OnSprite(int
mode, SpriteInfo&
spriteInfo,
BlockManipulation& spriteManipulation)
{
if (!enableSpriteManipulation)
return(true);
spriteManipulation.ambient = 0.35;
if (spriteInfo.index == 0)
{ // Ghost 1
spriteManipulation.voxelMode
= Voxel::SmoothEdge;
spriteManipulation.depthMapIndex = 0; // 0 is the default flat depth
map
spriteManipulation.reflective = 0.5;
}
else if (spriteInfo.index == 1)
{ // Ghost 2
spriteManipulation.voxelMode
= voxelMode; // Set the display mode to the user selected (see
OnKeyboard())
spriteManipulation.depthMapIndex = MapGhostId; // Use a special
depth-map. Map is request with OnGetDepthMap()
spriteManipulation.reflective = 16.0;
// Set the right sprite to more shiny
}
spriteManipulation.zScale = 5.0; // some more depth for the
sprites
spriteManipulation.rotationAxis1 = Rotation::Y; // some
animated rotation (see OnFrameEnd())
spriteManipulation.rotation1 = spriteRotationY;
spriteManipulation.rotationAxis2 = Rotation::X;
spriteManipulation.rotation2 = spriteRotationX;
spriteManipulation.zTranslation -= 0.08; // translate the
sprites a little mit more in foreground
return true;
}
void OnFrameEnd()
{
// Just some simple rotation around x and y axis
if (spriteRotationY < -80.0 && spriteRotationYDir < 0.0)
spriteRotationYDir = 0.7;
else if (spriteRotationY > 80.0 && spriteRotationYDir > 0.0)
spriteRotationYDir = -0.7;
spriteRotationY += spriteRotationYDir;
if (spriteRotationX < -15.0 && spriteRotationXDir < 0.0)
spriteRotationXDir = 0.1;
else if (spriteRotationX > 15.0 && spriteRotationXDir > 0.0)
spriteRotationXDir = -0.1;
spriteRotationX += spriteRotationXDir;
}
void OnTimer(int timerId)
{
if (timerId == startProgramTimerId)
{
APP.SendASCII("RUN\n");
}
}
grid<float>&
OnGetDepthMap(int mode, int index, bool front)
{
switch (index)
{
case MapGhostId:
return(mapGhost); // The only depth map we use
default: break;
}
return(mapEmpty);
}
void OnKeyboard(bool
pressed, Keys cbmKeyboard)
{
if (pressed)
{ // Change the display mode of our second sprite by the
key-input (keys 0 to 4)
if (cbmKeyboard == Keys::N0)
{
enableSpriteManipulation = false;
}
else if (cbmKeyboard == Keys::N1)
{
enableSpriteManipulation = true;
voxelMode =
Voxel::HardEdge;
GUI.ShowInfoMessage("\"Hard edge and block-style surface\" mode");
}
else if (cbmKeyboard == Keys::N2)
{
enableSpriteManipulation = true;
voxelMode =
Voxel::SmoothEdge;
GUI.ShowInfoMessage("\"Smooth edge and block-style surface\" mode");
}
else if (cbmKeyboard == Keys::N3)
{
enableSpriteManipulation = true;
voxelMode =
Voxel::SmoothSurface;
GUI.ShowInfoMessage("\"Hard edge and Smooth surface\" mode");
}
else if (cbmKeyboard == Keys::N4)
{
enableSpriteManipulation = true;
voxelMode =
Voxel::SmoothSurfaceEdge;
GUI.ShowInfoMessage("\"Smooth edge and Smooth surface\" mode");
}
}
}