The XAP development diary

This is a diary of my first commercial game development, for your amusement, enlightenment, and perusal.

I’ve mysteriously gained some kind of reputation on the 'net for Knowing Stuff but without ever having actually produced anything. So here goes: and indy game. Looking for a publisher! If you’re interested, get hold of me: cprince@puppygames.net

Now, it has to be said there have been many aborted attempts before by myself to write a game. You want to know why 95% of the games being written don’t get published? It’s because they don’t bloody get finished, that’s why.

But there’s other reasons. Massive overambition is the main one after failure to finish the thing, and is usually the cause of not finishing it in the first place. XAP is the final boil-down to the simplest game I want to make. I can’t make a game much simpler than XAP. It’s kinda retro, really, but there’s quite a market for people who want retro-style games. Look at PomPom and Llamasoft.

If I can’t finish XAP by February I’ll… I’ll… take a bit longer over it.

Before you ask, I suspect that it will be available for Win32 and Linux as a binary download, and possibly as a Java download too for those who already have JRE1.4 installed. It’ll be temptingly cheap enough to be affordable and just expensive enough to assure you that it won’t be a big bag of shite. And there will be a 4-level demo to get you introduced to a few of the basic aliens and maybe one big boss.

My usual offer goes out to the artists amongst you: if you take care of the art for me, there’s 20% of the profits in it for you. If you can do sound, there’s 10% in it for you. Just send me a portfolio…

And now, on with the diary.

Cas :slight_smile:

Having ripped the menu and GUI code out of a project on hold whilst Niels gets some free time to himself, XAP is born. The game design was thought of many years ago, so it’s a case of beautifying* it all and refining it somewhat.

For starters I’m going to code the very basic game, which is this: defend the blobs from the evil bubbles. When a bubble captures a blob it turns it into a Mad Jelly. When all the blobs die you are attacked by a swarm of Jellies. The bubbles are otherwise defenseless, so they have a backup alien, the Tringle, to help them. Tringles can shoot. If you spend too long on a level we will hurry you along by sending in a particularly vicious alien, the Gunner, which behaves like a Jelly on steroids, and isn’t worth any points either. As Jellies are particularly nasty as it is, the Gunner is worth avoiding. Periodically a new attack wave appears, or as soon as the player has killed all the existing aliens. After several attack waves the level ends.

Your ship is controlled by the mouse and the ship’s gun is targeted also by the mouse. The spacebar fires a smartbomb, and holding down the shift key activates a shield which discharges quickly. The shield can be used to kill enemies but it discharges even quicker, and the bigger the alien, the more it gets discharged. I think I’ll relate the collision discharge to the number of hits the alien needs before it dies.

Points are scored for rescuing blobs and killing enemies. A bonus is awarded at the end of the level for every blob left alive. Every 8 levels you get all your blobs back. Every level your shield is recharged according to how many blobs you have left.

The overall feel of XAP is going to be extremely hectic, breathless gameplay. You get no respite; and this should get you into the Zone, where your subconcious starts to play the game and your peripheral vision goes black. I’m in two minds about powerups; on the one hand, they add a bit of fun and variation; on the other, they always, always, always, spoil the balance of gameplay. I think this time round I might leave them out.

  • Any beautifying, of course, ain’t gonna be done by me…

Cas :slight_smile:

Today I put the player into the game, a stunningly disappointing purple circle. There’s a blue rectangle at the top of the screen for a status display, and the game area is sort of dark red. Not because it’s a nice colour; just because I wanted to make sure something got displayed.

After a multitude of false starts the player’s ship finally accelerates towards the mouse when the left button is held down. It takes very little time to realise that it’s going to accelerate clean out of the playing area, so I’ve put in a little bit of code to decelerate too.

I’m really going to need some help with the graphics :wink: Currently I’ve drawn single-frame graphics for each thing in the game, and no more. Ideally they all need to be lovingly rendered by a 3d Studio MAX genius… but of course Niels is busy. C’mon, help me out…

Lasers today. I’ve got the laser defined in XML, along with various parameters like its thickness and speed and range etc. etc. etc. so I can fiddle with it at leisure. Right now it looks beautifully Defender-esque, which fits the game design to a tee, as XAP is very firmly a Defender-clone.

The laser proved awkward in the end. It’s quite a complicated and expensive beast to produce - each laser is drawn with, say, 256 scaled sprites. This is a lot of sprites when you’ve got a whole bunch of lasers being drawn. If I just allowed 8 lasers that means I’ve used 2048 sprites just to draw them! That’s going to get a bit taxing on the low-end systems, like a TNT, which is my target low-end system - and I haven’t even thought about the aliens or the background or the particle effects yet…

Not only that, but the creation of a single laser involves creating about 8k of data and a large number of sprites. Fire that laser a hundred times and you’ve got nearly a megabyte of garbage to deal with and done no end of sprite addition and removal. I’d rather not let the whims of the garbage collector spoil the show, so the laser now incorporates a pool of instances, and they get recycled. Instantly there’s no garbage! Hurray! And I also discovered that by only drawing every other pixel of the laser I get approximately the same visuals but with twice the performance. Double hurray!

Currently they fade out in random colours. I’m not sure I like this; I think they need to boil away down a set gradient of colour.

I showed my wife the laser. She’s too young to remember much before 1984 :slight_smile: And she takes one look at this lovely laser, which I spent 6 hours straight getting perfect, and says, “It looks shit. It’s too blobby and messy.” etc. There’s no pleasing some people :wink: I tweaked the XML a bit but it needs those colours fixing. At least the background is now black.

On another note: in the original XAP I was limited by the Amiga and AMOS to having a static playing area. Quite hectic but not very cool. In the new XAP I think I’m going to scroll the playing area around and have a radar map in the middle of the screen. I’ll always have the player diagonallly opposite the mouse from the centre of the screen. I tried this out a couple of months ago in a quick test; it’s quite confusing at first, but you get used to it quickly.

I think tomorrow I’ll put the scrolling playing area in. I suppose that means I need a background, and I think a parallax background would look great and suitably retro. Being good and lazy with OpenGL I think that means I’ll be drawing three huge transparent quads on top of each other to give me a bit of depth. I might even squeeze the original XAP background in there somewhere, but it depends on fast line drawing and I seem to recall some of the older GL cards had awful line drawing ability, inexplicably.

Cas :slight_smile:

Today I have spent rather too much time - about 3 hours - tracking downa bug in the Server VM for 1.4.1_01. If only I’d known.

What was happening is that after whizzing around the screen testing the laser out for a while, the left mouse button would just mysteriously stop working. On closer inspection it turns out that it hadn’t stopped working, but that the JVM compiler had suddenly made an optimisation that caused a local integer variable which contained the mouse buttons state to suddenly have a rather random negative value, which is of course impossible if you only OR bits 1, 2, and 4 together…

So, back to the client VM.

Spot the obvious optimisation for lasers: why am I scaling them when they might as well be the right size in the first place? Duh. That’s saved a couple of thousand floating point operations…

Work on scrolling can begin now. This means I have to put the game panel into on of my GL scroll pane controls and turn off the scrollbars. All this does is translate and clip what’s drawn; I don’t envisage there being any advantage to figuring out if any sprites are outside the drawing area as GL will clip them more efficiently than I can.

Cas :slight_smile:

Here’s a screenie of a bit of the UI. It’s all rendered in realtime and animates nicely. Could perhaps do with some texturing on it or something:

And here’s that laser and pitiful player spaceship:

Cas :slight_smile:

Scrolling is now implemented, along with a rotating background. I turned off the clipping as things just vanished when they got to the edges of the scrolled component - most disturbing. But not as disturbing as the rotating background! There’s this odd iris pattern I knocked up in Cosmigo’s ProMotion. There’s three of them, in random colours, transparently overlaid on eacher other and rotating in different speeds in different directions. Every now and again they change direction. What with you zooming around the screen and the mouse changing the scrolled view instantly it gets really quite disorientating. Hopefully I’ll manage to make a few people sick!

The player can now zoom off into the distance and never return. I think I might have to put a limit on how far out of the game area you can roam. Or possibly I’ll just have you attacked by Gunners.

That’s enough of that for today. Tomorrow, I think we need to put the cute purple blobs in that you need to rescue.

Cas :slight_smile:

06/12/2002

Just before I went to bed last night I put in a colour fade sequence class, which smoothly interpolates between a sequence of colours. Very nice. The laser now boils away from white through yellow, orange, red, and finally evaporates into ultraviolet. It’s also a bit longer and faster now. Perfect. I’ll be using it to do some other special effects as well, including strobes. Whizz for stroboscopics! If you don’t throw up from the rotation I’ll make sure you have a fit instead. This will, of course, have an option to turn it off :slight_smile: You can’t be too careful these days.

This morning I went horseriding up in dense fog in the hills for two hours. I’m absolutely knackered and I’ve only really just got up!

I’m too lazy to put the purple blobs in so I’m going to have a bit of fun doing the background. First off is to make the layers of the rotating iris a bit parallax to give it more depth; then I’m going to have a stab at implementing a few layers of the original XAP “circuitry” background with them. Display lists is the way to go.

It’s fun starting work at 3pm.

Cas :slight_smile:

Oh dear. Well, I put the new parallax background in, in sort of transparent green circuitry, on three layers. I mean, it works and things… but it just looks shit. Ten years has been hard on an idea that was just a timesaving hack in the first place…

It has to go. I think I’ll just replace the whole circuits and rotation thing with a couple of huge textures.

Here’s a screenie for posterity:

Too bad you can’t see it moving. Well never mind, it sucks anyway.

Cas :slight_smile:

07/12/2002 1am

Put blobs and bubbles in the game. They aren’t animated at all, so they look exceedingly crap, rather like the player’s ship. However the background has undergone a re-evaluation, and is now a more colourful affair and actually looks quite nice in a retro abstract way.

The blobs sit around and occasionally jump about. The bubbles wander about in a diagonal fashion. Currently that’s all they do, because the collision detection code isn’t implemented yet (although it’s in there, there’s simply no action on a collision). Collision is going to be radius-based rather than bounding boxes for now, because it’s easier.

Time for bed.

Cas :slight_smile:

Collision detection has been implemented. This turned out to be a bit of a hassle as well. Originally I’d thought I could get away with just using a radius and doing collision detection that way. This generally works fine and providing the radii are small enough then you don’t get too many false hits, and when a few pixels scrape then you can just consider it a lucky escape. “Chalkdust!” as McEnroe used to yell at the umpire at Wimbledon.

Unfortunately the laser is lozenge shaped and moves very quickly - 32 pixels per frame - which is likely to see it sailing straight through some gidrahs. (The aliens are called gidrahs. Look it up.) So now, laser collision is done separately. When the laser is due to animate, it finds out all the gidrahs in a fairly large radius to itself, i.e. the radius of the circle which encompasses its entire 32 pixel line move. This gives us a very small shortlist of likely collision candidates. The laser then steps two pixels at a time towards its target, checking for collisions with gidrahs as it goes. The first one it hits usually stops it. In the worst case scenario, there will be 50 gidrahs crammed into a 32 pixel wide circle right next to the laser and it will somehow manage to move 16 times and have to check each gidrah for collisions. This is so utterly improbable it’s not worth worrying about. Two or three gidrahs is highly likely, and so is a collision with at least one of them, so I suspect that this means that a laser fired into a bunch of aliens incurs about 30 collision checks. Not going to break the bank I don’t think…

So now the blobs disappear when they’re shot, and so do the bubbles.

Tomorrow I won’t get much time to do anything as we’ve got friends round for dinner. Braised beef in port and stout with pickled walnuts and thyme with potatoes dauphinoise and redcurrant red cabbage, followed by drunken pears with rosemary cream. Should be nice.

But just in case I can squeeze in the time, I think it’s high time the aliens beamed in when they’re spawned and exploded into many tiny bits when shot, don’t you?

Technical Note

Collision is implemented as a closed system where all classes are known beforehand and extend from a base class, Entity, which has a radius and a position upon which to base its collision. When a collision occurs between two entities, both are informed simultanously of the collision:


if (entity.isTouching(this)) {
      entity.inCollisionWith(this);
      this.inCollisionWith(entity);
}

In Entity, there is an inCollisionWith() method which further breaks down the collision into specific known classes of collision and dispatches the correct method “in reverse”. This is fine providing you never try to call the specialised inCollisionWithXXX() methods directly as the reversing will not happing and you’ll get a one-sided collision where one party has no action performed upon it:


abstract class Entity {

      abstract void inCollisionWith(Entity entity);
      
      // Default behaviour is to ignore the collision
      void inCollisionWithLaser(Laser laser) {}
      void inCollisionWithPlayer(Player player) {}
      void inCollisionWithBlob(Blob blob) {}
      void inCollisinoWithGidrah(Gidrah gidrah) {}

}

class Bubble extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithBubble(this);
      }
      void inCollisionWithLaser(Laser laser) {
            // Oh no, we've been shot!
            kill();
      }
}

class Gidrah extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithGidrah(this);
      }
      void inCollisionWithLaser(Laser laser) {
            // Oh no, we've been shot!
            kill();
      }
}

class Player extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithPlayer(this);
      }
      void inCollisionWithGidrah(Gidrah gidrah) {
            // Oh no, we've hit an alien
            kill();
      }
}

class Laser extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithLaser(this);
      }
      void inCollisionWithGidrah(Gidrah gidrah) {
            // Hit something, so stop the laser
            kill();
      }
      void inCollisionWithBlob(Gidrah gidrah) {
            // Hit something, so stop the laser
            kill();
      }
}


Cas :slight_smile:

Now the bubbles explode in a satisfying shower of burning particles. Not bad for an hours’ work under the influence of a bottle of wine.

Definitely retro.

(Food for fact freaks: each explosion consists of no less than 128 different particles whizzing off in different directions and different velocities, with a total duration of approximately one second)

Cas :slight_smile:

At last, the evil Mad Jelly lives (although he doesn’t shoot yet). In order to give me plenty of cannon fodder to playtest with the bubbles automatically spawn at random intervals giving me infinite gidrahs to zap. As a strange side effect of this, they appear on the title screen as well. I suppose that’ll have to stop…

And another strange thing about the title screen is it sometimes hangs around in the background whilst you’re playing the game. No idea why yet, but I’m sure it’s trivial.

So, the bubbles now capture blobs, and after about 4 seconds they turn them into a nasty green jelly. When I first put the jellies in they just shot towards the player like a … a… rabid jelly. It’s difficult to describe what it looks like when a small swarm of green jellies hurtle towards you intent on death. Then they just sit there wobbling at you, because currently there’s no code to kill the player :slight_smile:

So the jellies got slowed down a bit and at least there’s a small chance of shooting them before they get you.

I even remembered all the daft fringe cases like the blob gets shot by the player accidentally in a bungled rescue attempt, or the bubble gets zapped and the blob gets rescued etc.

Also, I put in an alien res-in effect, using a shrinking glow effect and a few particles whizzing together. Looks quite nice but might need more tweaking. This gives you about 1 second to avoid having an alien res in on top of you. Fortunately they still can’t kill you of course.

Reduced explosions to 64 particles. Seems like enough. You should see what it looks like when you waste five bubbles in a row, it’s like bonfire night.

Cas :slight_smile:

At last, you can die! In a huge shower of particles, of course. All the effects, it has to be said, look pretty much the same, so they’re going to have to be fiddled with. In particular I need some different particle sprites to the rather boring ‘spotlight’ glow, which isn’t even animated.

With death comes reincarnation. You get a second or two pause after death, and then you rez in in a swirl of … particles. (Guess what - I like particles :slight_smile: ) This gives you a moment to position yourself somewhere where the aliens aren’t. The view suddenly snaps into place once you materialize which is rather disconcerting so I think that’s going to have to be a smoother affair, but I’ll put that in later when I’m tuning it all.

Strange things happen when you run out of lives. The title screen reappears unexpectedly. All the particles remain frozen in space, but the gidrahs keep trundling around!

We also now have the mighty Tringle to defend the bubbles. The Tringle is also hopelessly drawn, as if by an idiot, such as me. It’s red, triangular, and rather obviously not very mean. It wanders around in roughly the same pattern as the bubbles right now, and it doesn’t even shoot yet so it’s pretty useless.

With tringles we now have attack waves and multiple levels.

A new attack wave comes after a timeout (currently 30 seconds on the first level), or when there’s only one gidrah left on the screen. (To keep track of how many gidrahs are on the screen, the Gidrah class gets a static int, and the constructor increments it, and the doFuneral() method decrements it).

Cas :slight_smile:

Added a small new feature to particles to make them change in size over time by a fixed amount. Slightly prettier as a result, but still not as good as having some proper particle sprites to choose from.

XAP has gotten a little messy now with all the XML and features stuff. Here’s how it works:

During development I run a XAP Resources Converter, which loads an XML file, which then maps tags to classes called Resources. Whenever a tag is encountered, I create a new instance of the class and stuff it in a Map with a name, along with its parsed attributes and other data.

Some of the instances are effectively singletons; the Player is a singleton. I declare a mapping to it, include it just once, and then maintain a single instance of the player as a static variable on the Player class itself.

Some of the instances are “templates”: each of the gidrahs is a template. For example, I map the " tag to xap.gidrahs.Bubble, and create a single instance of Bubble with the name “gidrah_bubble”.

What I can now do is get this template Bubble instance like so:


Bubble masterBubble = (Bubble) Resources.get("gidrah_bubble");

I can then use the template to spawn a copy of the Bubble - ie. create a new alien to plonk in the game:


Entity.spawn(masterBubble);

There’s a spawn() method on Entity (the superclass of Gidrah, which is in turn the superclass of Bubble) which calls all the relevant stuff to create me a new alien.

So what’s all this Resources thing doing then?

Well, Resources is a way of stashing all the information about a thing that you want, without it actually having to really exist. Not only are there gidrahs and game levels etc. in there but I’m putting all my textures and (soon) sound effect in there too.

When I want a Resource, I look it up by its name. If the resource hasn’t been created yet, then it goes off and does whatever clever stuff it needs to do to become created. In the case of a GLTexture, for example, I load in a binary image file and call the various GL commands to upload the texture into OpenGL.

I can then explicitly destroy() Resources when I don’t want them any more, which will unload anything that’s needed to be unloaded, but which leaves me with the raw uncreated Resource hanging around just in case I ask for it to be created again.

So back to the resource converter: its output is a nice serialized HashMap of resource names to serialized resource objects, all waiting to be created when needed. This lets me ship the game without needing all the XML APIs installed; the only classes dragged in are a few of the interfaces and supporting classes.

Now I’m going to wrestle with OpenAL and try to figure out how to make a suitably menacing laser zap.

Cas :slight_smile:

Well I’ll be dipped in dogshit! I wrote some ALBuffer and ALSource classes for the Shaven Puppy Game Library and wrote a .WAV -> .jgwave converter (my own special format which I understand :slight_smile: ), and every Entity now gets an ALSource. I’m not sure if that’s wise but anyway - the laser was the first to get a noise, and it’s a proper laser noise! None of this quiet “pewww, pewww” pingy rubbish - this laser sounds like it’s going to hurt!

Die alien scum!

However, I have had less success with the res-in noises, and most disappointing of all, the explosions :frowning:

Basically, they just aren’t working and I don’t know why yet…

Cas :slight_smile:

Brian suggested to me that creating 500 OpenAL sound sources might have been the problem :slight_smile: I was just treating them like OpenGL textures, i.e. a relatively unlimited resource, and I was expecting the OpenAL drivers to try and cope with whatever hardware it has to mix them. Wrong! Seems like I can only rely on about 8 of them actually being present. It’s a bit annoying I don’t seem to be getting an exception if I ask for sources and they can’t be created. More investigation with Brian about that one.

What I’ve got now is a SoundPlayer class which maintains a little pool of 8 ALSources, each associated with a priority and the time it was last told to play a sound. When I want to play a new sound I search for the oldest lowest priority sound effect and stop it, and then play the new sound using it.

It’s not quite perfect as some fairly low-priority but long lasting sound effects can get cut off a bit too soon. I think I should really calculate how long each sound is going to play for and mark them unused after that time, so I can always pick a source with no sound effect currently playing in it. So that’s on the “to-do” list.

Cas :slight_smile:

Not much time on the game today. Out riding horses for a couple of hours. Ouch! Tried to create a decent explosion sound effect for when the player gets fingered. Ended up with something that sounds rather like a crisp packet going pop :frowning: Igore, more work at the labs!

Oh, I remember what I did now: gidrahs can now shoot! Quite an amusing start to it as well. I got the probability that a gidrah will shoot a bit wrong and immediately on appearing the tringles set about blasting the player with a huge cloud of deadly plasma balls. (And due to another bug they flew at the player at hundreds of pixels per second - resulting, of course, in instant death).

So the tringles now shoot much more rarely. Jellies and Gunners shoot at regular intervals as they home in on the player. They seem to be moving faster than their bullets which is perhaps not quite right. Much bullet speed tuning is required.

Cas :slight_smile:

There are lots of niggling things that are beginning to annoy me in XAP now which need to be fixed. There’s a glitch with the sprites that sees them flicker quite a lot; this is something to do with NV_vertex_array_range. It needs fixing.

When you die with the mouse button held down you fire a laser upon reappearing. By a stroke of incredibly bad luck this always seems to point at one of the cute purple blobs. Splat!

And when you die the res-in sound effect starts too early (i.e before the actual res-in starts, in the “death delay”). And when you’ve finished appearing, there’s a cluster of particles left hanging about for a bit.

When the game ends none of the particles vanish in your final explosion. And if you start a new game all the existing gidrahs are still there!

So it’s time to make a big mongy list of Things To Do and work them through one by one before I continue. Someone once told me that you are vastly more likely to achieve goals when you actually write them down. This can backfire slightly of course - I’ve written down such chores as “tie shoelaces” and “eat lunch” before - but by and large it’s a great technique for getting things done. I shall post the list up here when it’s full of stuff and tick them off in the coming days.

Cas :slight_smile:

  • Alien bullets should be a single sprite: currently I’m (wastefully) drawing a blue halo under a central flickering white core, which looks nice but really should just be one sprite… and it would be nice if it left a little teeny trail of sparks too, and some smoke, like a sparkler.

  • fix sound problems. Oh, how these are the bane of my life. Apart from being crap they don’t play when they should, still. It all starts off OK, then after a while, one by one, they just sort of don’t happen any more. Except for the laser, which seems to be the only one not affected. It’s terribly difficult to figure out if it’s OpenAL or me.

  • when all the gidrahs die go to the next level. This involves the blob bonus screen where you get points for surviving blobs.

  • try and think of a better background.

  • put in shield code for player. Hold down left shift, on comes the shield.

  • when all blobs die make swarm of jellies appear

  • adjust alien bullet speeds to get them just right.

  • adjust player’s max speed to cope with the bullets and jellies.

  • do better alien res-in effect. I have some ideas about concentric rainbow circles. Hippy ideas I suppose. I admit to being heavily Yakfluenced. But then, Yak’s games were always the best ones. Oh, and Andy Braybrook’s too. Them were the days etc.

  • do better player res-in effect. It’s really rather lame, just a bunch of dots spiralling in from space.

  • maybe go to slight 3d perspective so I can have particles flying in the air a little bit. It’ll look better when there’s a more reasonably solid background and shadows under the sprites.

  • draw some particle animations - the current “spotlight” effect is great as a
    general purpose particle but really I need some nice animated hoops and sparkles as well.

  • better alien death - make particles fly in direction of damage? That would be nice. When a laser bolt slams into the side of a gidrah the bits could fly off in the appropriate direction.

  • put up Game Over sequence

  • remove leftover crud when the game ends like particles etc

  • find out why the level doesn’t appear to reset when you start a new game: all the last gidrahs are still there and the gunner usually appears immediately.

  • do some blob sound effects: a wee scream when they get shot; a suitable noise when they’re captured by a bubble; a bonus noise when you rescue them from a bubble; a bonus noise when you rescue them from a bubble with style and panache; and the noise of a Mad Jelly appearing - I seem to recall sampling the maniacal cackle at the start of a song called Lucretia by Megadeth last time round which I think I might use again.

  • put the mouse crosshairs in. Depending on what you’re pointing at the mouse crosshair changes. For example it changes to a “don’t shoot” crosshair if you wave it over a blob.

  • blob farming. I can’t remember now if this was in the original one, but I always thought that dragging the mouse over blobs should coax them to move where you want them.

  • make the bubbles appear in the proximity of a randomly chosen blob.

  • make a little bonus score appear if you rescue a blob

  • smartbombs: tap ctrl key, eat nuclear death gidrahs!

  • position player in the middle of the battlezone at the start of the level.

  • smooth movement from the current scroll position to the desired scroll position to prevent nasty view snap when the player beams in.

Cas :slight_smile: