Well. I had made that kind for that stage though I plan to change the setup for the bike riders to match the way the original SFA2 stage has later. That was my first to get that working. Let me give you a trick which may not work for everyone but does work in a logical sense (depending on the build/version they are using?). Here's how I apply it.
What you need to look at is the width size/number of each sprite from three parts: an entity (sprite) with its own pixels of width, a current panel size, and a current screen/video resolution you are using. Here are the three parts in this example before I give you the most important part for this.
Some samples of an entity sprite with its size of width. (One is measured 256 while the other is 112.)
View attachment 10370
(
256x41)
View attachment 10371
(
112x45)
View attachment 10373
(
122x58)
A panel size for a scrollable purpose, but you don't have to make the background image all blank like this one. Plus, this is the panel image I am using for the level.
View attachment 10372
(
720x244)
A current screen resolution. (
320x240)
View attachment 10369
If you are going to spawn an entity in a stage, you need the most important part for it. It's called offscreenkill. It kills off an entity that is far off the screen.
Here's where the real part comes in.
First, let's start off with one of the entities/sprites I showed, and that's the one with the longest width (256x41). Don't worry about its height dimensions, like 41. Here, I named this entity "behind" because it's the most hidden entity from being seen though you can see it behind all of them (a little). How can we use the value of offscreenkill to kill off the entity that is farther away from the screen while you're scrolling through where it's moving along before it vanishes? Do a little/simple math or measure the 3 parts. Calculate the width numbers of those I gave out from the sample for the screen resolution, the entity, and the panel size. For example, here's the entity named "behind". Its width dimension is 256 as I said. It would go off screen depending on how far the camera scrolls. If its offscreenkill value is 100 and it idles in the stage, the camera scrolls 100 pixels passed by that entity. That's when it vanishes. If you go back to it, it's gone.
But now with the current panel size (720), subtract the number of its width of the resolution (320) for scrolling. Then, you add a number of the width from the entity (256) for going off screen, so that the game won't lag. This will help the game not consume memory. If you don't use offscreenkill, it will consume more memory and it would either lag the gameplay experience or start a crash. This is why using offscreenkill is important. To check the engine's performance in regard to memory and/or how many sprites exist, press F12 or go to the Options Menu and select System Options. Go to Debug Settings and turn on its performance option. You will see whether it increases memory or not.
Take a look at the notes about the use of offscreenkill here along with how the numbers are calculated.
Code:
name behind
type none
speed 10
facing 1
offscreenkill 656 #720 - 320 = 400 + 256 = 656
#offscreenkill 656 # 656 (width of panel - width of current screen resolution) + width of sprite used in animation = number for offscreenkill ; e.g. (720 - 320) = 400 + 256 = 656
animationscript data/scripts/script.c
anim idle
loop 1
offset 1 41
delay 8
@cmd velo001 1 0 0
frame data/bgs/chun-li/1_3-0.png
frame data/bgs/chun-li/1_3-1.png
frame data/bgs/chun-li/1_3-2.png
frame data/bgs/chun-li/1_3-3.png
frame data/bgs/chun-li/1_3-4.png
frame data/bgs/chun-li/1_3-5.png
C:
void velo001(float fX, float fZ, float fY){
//velo001
//Damon Vaughn Caskey
//05/06/2007
//
//Replicates movement effect.
//
//fX: X axis speed.
//fZ: Z axis speed.
//fY: Y axis speed.
void vSelf = getlocalvar("self"); //Get calling entity.
if (getentityproperty(vSelf, "direction")==0){ //Is entity facing right?
fX = -fX; ////Reverse X direction to match facing.
}
changeentityproperty(vSelf, "velocity", fX, fZ, fY); //Apply movement.
}
Even though I put velo001 for its mobile movement, don't worry about adding it (as a beginner) until we get to the last part. Unless you know how to do it or wanna put a mobile movement of speed in there, sure, that's up to you.
Here I have this level header for this particular stage from the example.
Code:
bglayer data/bgs/chun-li/1_0-0.png 0 0 0 0 0 0 1 1 1 0
fglayer data/bgs/chun-li/1_17-0.png -70 0 0 0 0 0 0 1 1 1 0
bglayer data/bgs/chun-li/1_2-0.png 0 0 0 209 0 0 1 1 1 0 # Floor
direction both
order a
settime 0
notime 1
type 1
panel data/bgs/chun-li/chun-li_panel3.png
Depending on the panel size I am using and the sprite that is near the screen edge, I spawn a couple of these in case you move forward quick in the start of the level.
Code:
#### BIKE GROUPS
### Bike behind
spawn bikespawner 1
coords -256 177
at 0
spawn behind 1 #behind
coords 0 177
at 0
spawn behind 1
coords 256 177
at 0
spawn behind 1
coords 512 177
at 0
About that "bikespawner" entity I put there, there's a good reason why I included it. It's about spawning it repeatedly as you see its code here. Yes, I leave its offscreenkill value long, so it wouldn't kill itself every time you are farther away from it.
Code:
name bikespawner # Spawning the bike riders
type none
facing 1
subject_to_minz 0
speed 10
load behind
load bicyclists
load bicyclists2
load bicyclists3
load bicyclists4
offscreenkill 100000
animationscript data/scripts/script.c
anim spawn
offset 1 1
delay 1
frame data/chars/misc/empty.gif
anim idle
loop 1
delay 1
offset 1 1
@cmd spawner "behind" 0 0 0 #spawner {name} {x} {y} {z}
frame data/chars/misc/empty.gif #Spawn
delay 127
frame data/chars/misc/empty.gif #Stop
C:
void spawner(void vName, float fX, float fY, float fZ)
{ //Spawns entity next to caller and set them as child.
//
//vName: Model name of entity to be spawned in.
//fX: X location adjustment.
//fZ: Y location adjustment.
//fY: Z location adjustment.
void self = getlocalvar("self"); //Get calling entity.
void vSpawn; //Spawn object.
vSpawn = spawn01(vName, fX, fY, fZ); //Spawn in entity.
changeentityproperty(vSpawn, "parent", self); //Set caller as parent.
return vSpawn; //Return spawn.
}
This script called "spawner" calls the spawned entity in its certain location.
For another entity called "bicyclists", use the same formula from the sample. (You don't have to use subject_to_minz 0 unless something goes wrong.)
Code:
name bicyclists
type none
subject_to_minz 0
speed 9
facing 1
offscreenkill 512 # 720-320=400+112
#offscreenkill 816 # 816 (width of panel - width of current screen resolution) + width of sprite used in animation = number for offscreenkill ; e.g. (1024 - 320 = 704) + 112 = 816
animationscript data/scripts/script.c
anim idle # Color 1
loop 1 1
delay 1
offset 1 45
frame data/bgs/chun-li/1_5-0.png
delay 12
@cmd velo001 1 0 0
frame data/bgs/chun-li/1_5-0.png
frame data/bgs/chun-li/1_5-1.png
frame data/bgs/chun-li/1_5-2.png
frame data/bgs/chun-li/1_5-3.png
frame data/bgs/chun-li/1_5-4.png
frame data/bgs/chun-li/1_5-5.png
frame data/bgs/chun-li/1_5-6.png
frame data/bgs/chun-li/1_5-7.png
anim freespecial # Color 2
loop 1 1
delay 1
offset 1 45
frame data/bgs/chun-li/1_6-0.png
delay 12
@cmd velo001 1 0 0
frame data/bgs/chun-li/1_6-0.png
frame data/bgs/chun-li/1_6-1.png
frame data/bgs/chun-li/1_6-2.png
frame data/bgs/chun-li/1_6-3.png
frame data/bgs/chun-li/1_6-4.png
frame data/bgs/chun-li/1_6-5.png
frame data/bgs/chun-li/1_6-6.png
frame data/bgs/chun-li/1_6-7.png
anim follow1 # Color 3
loop 1 1
delay 1
offset 1 45
frame data/bgs/chun-li/1_7-0.png
delay 12
@cmd velo001 1 0 0
frame data/bgs/chun-li/1_7-0.png
frame data/bgs/chun-li/1_7-1.png
frame data/bgs/chun-li/1_7-2.png
frame data/bgs/chun-li/1_7-3.png
frame data/bgs/chun-li/1_7-4.png
frame data/bgs/chun-li/1_7-5.png
frame data/bgs/chun-li/1_7-6.png
frame data/bgs/chun-li/1_7-7.png
anim freespecial2 # Color 4
loop 1 1
delay 1
offset 1 45
frame data/bgs/chun-li/1_8-0.png
delay 12
@cmd velo001 1 0 0
frame data/bgs/chun-li/1_8-0.png
frame data/bgs/chun-li/1_8-1.png
frame data/bgs/chun-li/1_8-2.png
frame data/bgs/chun-li/1_8-3.png
frame data/bgs/chun-li/1_8-4.png
frame data/bgs/chun-li/1_8-5.png
frame data/bgs/chun-li/1_8-6.png
frame data/bgs/chun-li/1_8-7.png
The difference is you need to spawn it with a different animation along using script in the level like bikespawner has. Plus, I spawned other bicyclists with different animations.
Code:
#### Bike next to traffic man
spawn bikespawner 1
@script
void main(){
void self = getlocalvar("self");
performattack(self, openborconstant("ANI_FREESPECIAL"));
}
@end_script
coords -112 183
at 0
spawn bicyclists 1
coords 0 183
at 0
spawn bicyclists 1
@script
void main(){
void self = getlocalvar("self");
performattack(self, openborconstant("ANI_FOLLOW1"));
}
@end_script
coords 112 183
at 0
spawn bicyclists 1
@script
void main(){
void self = getlocalvar("self");
performattack(self, openborconstant("ANI_FREESPECIAL"));
}
@end_script
coords 224 183
at 0
spawn bicyclists 1
@script
void main(){
void self = getlocalvar("self");
performattack(self, openborconstant("ANI_FREESPECIAL2"));
}
@end_script
coords 336 183
at 0
spawn bicyclists 1
coords 448 183
at 0
spawn bicyclists 1
@script
void main(){
void self = getlocalvar("self");
performattack(self, openborconstant("ANI_FOLLOW1"));
}
@end_script
coords 560 183
at 0
Here's another animation for the same entity called "bikespawner".
Code:
anim freespecial # Spawning each group of 4 bicyclists
loop 1
delay 1
offset 1 1
@cmd spawnen "bicyclists" "ANI_IDLE" 0 0 0
frame data/chars/misc/empty.gif
delay 56
frame data/chars/misc/empty.gif
delay 1
@cmd spawnen "bicyclists" "ANI_FOLLOW1" 0 0 0
frame data/chars/misc/empty.gif
delay 56
frame data/chars/misc/empty.gif
delay 1
@cmd spawnen "bicyclists" "ANI_FREESPECIAL" 0 0 0
frame data/chars/misc/empty.gif
delay 56
frame data/chars/misc/empty.gif
delay 1
@cmd spawnen "bicyclists" "ANI_FREESPECIAL2" 0 0 0
frame data/chars/misc/empty.gif
delay 56
frame data/chars/misc/empty.gif
This script spawns an entity but with a specific animation.
C:
void spawnen(void Name, void Ani, float dx, float dy, float dz){
//Modified by Max Man
//Date: 01/29/2018
//Updated: 11/23/2021
//Spawning a spawned entity with its own animation
void self = getlocalvar("self");
void vSpawn;
vSpawn = spawn01(Name, dx, dy, dz, 0);
changeentityproperty(vSpawn, "animation", openborconstant(Ani));
}
I put/labeled the notes in the level so I wouldn't forget or get confused about how/where I put those parts. Also, after you finished setting them up, you can use velo001 for moving mobile. That way they will move with a smooth speed you want. There are other scripts you can use to get that working but that will come some other time.
I think that wraps up on the use of spawning an entity repeatedly. But if you want to change colors for your cars only instead of making same sprites for each color, let me know here. You can use alternate palettes for this so you wouldn't waste your time editing colors for same animations.
I'm very sorry for the script,
@Bloodbane. I don't mean to take credit from you for using a similar script as yours. But I forgot what your script for spawning a specific animation with position is like. I created it myself because I wanted to spawn an entity name with its specific animation for my own. Plus, I forgot the name of your specific script that does it similar. I named it "spawnen" but forgot the name of yours you created.