I've made a one liner - called Line

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

You can remove this statement from the GAME OVER sequence:

Code: Select all

POKE q,1
At this point, you will already have INK 1 and PAPER 0. The only effect practical effect of this statement is to disable BRIGHT, but it's nearly impossible to distinguish brightness with these colors anyway.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

patters wrote: Tue Jul 30, 2019 12:31 pm There is one slight edge case to my game. In order to keep the action reasonably fast I DRAW the line in increments of two pixels rather than PLOTing each point. Since the attributes are only checked every two pixels of line it's possible for the line to clip across the corner pixel of an obstacle and turn it blue without a collision. A necessary design compromise though...
To fix this bug, change the start position from (8,85) to (8,84).
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Great tips, from the master himself :)

I was just experimenting with the collision detection. The star character is quite small relative to the character block so I was wondering about whether to change it to use POINT rather than ATTR. Drawing each pixel on the line with PLOT is still considerably slower, but if I stick to DRAWing in increments of two I can validate the POINT status at both points for roughly the same overhead as one ATTR lookup. This would allow the line to really skim the obstacles and would make the game feel a lot more fair. Colour clash can be somewhat mitigated by making the entire playfield INK 1 and rendering the line with INK 8. This is less jarring than the line turning obstacles blue. I'll fold in your improvements and post a new version here to see whether people prefer it.
Last edited by patters on Tue Jul 30, 2019 9:06 pm, edited 1 time in total.
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Einar Saukas wrote: Tue Jul 30, 2019 8:17 pm To fix this bug, change the start position from (8,85) to (8,84).
How did I not see that. :lol:
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

patters wrote: Tue Jul 30, 2019 9:04 pm Great tips, from the master himself :)
Thanks! :)

patters wrote: Tue Jul 30, 2019 9:04 pm I was just experimenting with the collision detection. The star character is quite small relative to the character block
I think it would look good to use the hash sign '#', but setting a different PAPER instead of INK.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

Einar Saukas wrote: Tue Jul 30, 2019 10:04 pm I think it would look good to use the hash sign '#', but setting a different PAPER instead of INK.
Another idea is to use either hash sign '#' or capital 'O', setting PAPER 1 and a different INK. It will give the impression there's a faint force field around each obstacle. This way, these obstacles won't look as blocky, but the collision will always seem correct.

Yet another option is using the copyright symbol that fills almost the entire character block, but I don't think it will look as good.
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Hmm. I've really convinced myself that ATTR collision detection is not a good fit here, so I've switched to POINT. The main issue is that as the later levels get congested with obstacles, the player needs to be able to cut a diagonal between closely packed obstacles. If you can't do this then it seems too unfair. This is a remake of a game I had played at school, and on that computer I'm pretty sure collisions were pixel accurate, so this feels more faithful.

Code: Select all

FOR l=1 TO 20:
POKE 23693,65:
BORDER 0:
CLS :
INK 2:
PLOT 2,170:
FOR n=0 TO 1:
DRAW 247,0:
DRAW 0,n+n-164:
DRAW n+n-248,0:
DRAW 0,163:
NEXT n:
PRINT INK 3;"LEVEL ";l:
FOR n=9+(l>9) TO 12-(l>9):
PRINT AT n,31; INK 1;" ":
NEXT n:
INK RND*4+3.5:
FOR n=0 TO l*3+20:
PRINT AT RND*18+1.5,RND*26+3.5;"*":
BEEP .0001,60:
NEXT n:
INK 8:
LET y=85:
PLOT 8,y:
FOR x=5 TO 125:
LET k=4*(INKEY$<>"")-2:
LET y=y+k: POKE 23620*POINT (2*x,y),34:
DRAW 2,k:
NEXT x:
BEEP .01,20:
BEEP .01,30:
NEXT l:
DIM a$(32):
BRIGHT 0:
INK 1+5*(l=21):
FOR n=0 TO 6:
BEEP .005,20-5*n:
NEXT n:
FOR n=0 TO 10:
PRINT AT n,0; OVER 1;a$;AT 21-n,0;a$:
NEXT n:
PRINT AT 10,n; INK 7;"GAME OVER" AND l<21;"WELL DONE" AND l=21
Download link

The game is a bit faster now which I think makes it more addictive, but it's a lot more achievable though still challenging. In fact I just completed it for the first time. I've improved the sound a bit, and added a completion screen. The collision detection is only checked every two pixels on the line, but I think with the current grid alignment it's working well. What do you think Einar?
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Here is a version which sacrifices the better sounds in order to offer the player three lives with a visual indicator in the bottom right of the screen. Given that the game runs faster, I think this is a good addition. In order to get it under the one screen limit I have had to re-use the 'e' variable a few times.

Code: Select all

READ p,q,e,l,d$:
FOR d=0 TO 2:
POKE q,65:
BORDER 0:
CLS :
INK 2:
PLOT 2,170:
FOR n=0 TO 1:
DRAW 247,0:
DRAW 0,n+n-164:
DRAW n+n-248,0:
DRAW 0,163:
NEXT n:
PRINT INK 3;"LEVEL ";l:
FOR n=9+(l>9) TO 12-(l>9):
PRINT AT n,31; INK 1;" ";AT 20,29+d;d$( TO 2-d):
NEXT n:
INK RND*4+3.5:
FOR n=0 TO l*3+e:
PRINT AT RND*18+1.5,RND*26+3.5;"*":
NEXT n:
INK 8:
LET y=85:
PLOT 8,y:
FOR x=5 TO 125:
LET k=4*(INKEY$<>"")-2:
LET y=y+k:
POKE p*POINT (2*x,y),34:
DRAW 2,k:
NEXT x:
LET l=l+1:
BEEP .02,30:
POKE p,3+33*(l=e):
BEEP .2,-e:
NEXT d:
DIM a$(32):
INK 1+5*(l=e):
FOR n=0 TO 10:
PRINT AT n,0; OVER 1;a$;AT 21-n,0;a$:
NEXT n:
PRINT AT 10,n; INK 7;"GAME OVER" AND l<e;"WELL DONE" AND l=e:
DATA 23620,p+73,21,1,"//"
Download link

Any further optimisations here that might allow the sounds as well, particularly the obstacle placement beep?
Last edited by patters on Wed Jul 31, 2019 2:03 pm, edited 4 times in total.
User avatar
Joefish
Rick Dangerous
Posts: 2042
Joined: Tue Nov 14, 2017 10:26 am

Re: I've made a one liner - called Line

Post by Joefish »

If it's only checking every 2 pixels, surely you need obstacles that have two-pixel thick lines so you don't skip straight through one?
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Joefish wrote: Wed Jul 31, 2019 1:30 pm If it's only checking every 2 pixels, surely you need obstacles that have two-pixel thick lines so you don't skip straight through one?
I have play tested it a lot and I think it's fine. The border lines are two pixels thick, and the stars don't really have corners to skip though if you're on a diagonal trajectory. Basically if you're going to clip the star at all you'll hit it with the subsequent pixel - mainly because of the current grid alignment (which can only change by 2 units at a time). Give it a try. I just updated the latest version btw. Had some issues with it which are now resolved, but it's been tricky to get it back under the one screen limit.
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

patters wrote: Wed Jul 31, 2019 12:31 pm Here is a version which sacrifices the better sounds in order to offer the player three lives with a visual indicator in the bottom right of the screen.
Updated again to combine the creation of the gate into the red playfield outline loop. Is there a tighter way to encode these DRAW operations I wonder...

Code: Select all

READ p,q,e,l,d$:
FOR d=0 TO 2:
POKE q,65:
BORDER 0:
CLS :
INK 2:
LET g=8*(l>9)
PLOT 2,170:
FOR n=0 TO 1:
DRAW 247,0:
DRAW 0,n-66-g:
PLOT 249-n,71+g:
DRAW 0,n-65-g:
DRAW n+n-248,0:
DRAW 0,163:
NEXT n:
PRINT INK 3;"LEVEL ";l;AT 20,29+d; INK 1;d$( TO 2-d):
INK RND*4+3.5:
FOR n=0 TO l*3+e:
PRINT AT RND*18+1.5,RND*26+3.5;"*":
NEXT n:
INK 8:
LET y=85:
PLOT 8,y:
FOR x=5 TO 125:
LET k=4*(INKEY$<>"")-2:
LET y=y+k:
POKE p*POINT (2*x,y),34:
DRAW 2,k:
NEXT x:
LET l=l+1:
BEEP .02,30:
POKE p,3+33*(l=e):
BEEP .2,-e:
NEXT d:
DIM a$(32):
INK 1+5*(l=e):
FOR n=0 TO 10:
PRINT AT n,0; OVER 1;a$;AT e-n,0;a$:
NEXT n:
PRINT AT 10,n; INK 7;"GAME OVER" AND l<e;"WELL DONE" AND l=e:
DATA 23620,p+73,21,1,"//"
Download link
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

Instead of this:

Code: Select all

FOR d=0 TO 2: ...       PRINT INK 3;"LEVEL ";l;AT 20,29+d; INK 1;d$( TO 2-d)
Use this:

Code: Select all

FOR d=1 TO 3: ...       PRINT INK 3;"LEVEL ";l;AT 20,28+d; INK 1;d$(d TO )
However the lives indicator looks much better using INK 3. In this case, the code will be much shorter:

Code: Select all

FOR d=1 TO 3: ...       PRINT INK 3;"LEVEL ";l;AT 20,28+d;d$(d TO )
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

Replace:

Code: Select all

FOR n=0 TO l*3+e
with:

Code: Select all

FOR n=-e TO l*3
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

You can also consider replacing this:

Code: Select all

PRINT AT RND*18+1.5,RND*26+3.5;"*"
with this:

Code: Select all

PRINT AT RND*17+2,RND*25+4;"*"
It won't work exactly the same way, since the incidence of stars in the first and last rows, also first and last columns, will be reduced by 50%. But I think it looks even better this way. It looks good to have a higher concentration of stars closer to the center of the galaxy, not as many stars near the edge...

Alternatively you could expand the stars area sideways, to make the game a little more challenging, as follows:

Code: Select all

PRINT AT RND*17+2,RND*27+3;"*"
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

I suggest replacing this:

Code: Select all

POKE p*POINT (2*x,y),34
with this:

Code: Select all

POKE p*POINT (x+x,y),34
It's the same size, but runs a little bit faster.
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

patters wrote: Wed Jul 31, 2019 7:13 pm Updated again to combine the creation of the gate into the red playfield outline loop. Is there a tighter way to encode these DRAW operations I wonder...
To produce exactly the same red outline, replace this:

Code: Select all

LET g=8*(l>9): PLOT 2,170: FOR n=0 TO 1: DRAW 247,0: DRAW 0,n-66-g: PLOT 249-n,71+g: DRAW 0,n-65-g: DRAW n+n-248,0: DRAW 0,163: NEXT n
with this:

Code: Select all

LET g=8*(l>9): FOR n=0 TO 1: PLOT 249-n,71+g: DRAW 0,n-65-g: DRAW n+n-248,0: DRAW 0,163: DRAW 247,0: DRAW 0,-n-65-g: NEXT n
However, gameplay works much better if the gate becomes gradually narrower after each level, instead of reducing size only once at level 10. This change will also make this code a lot shorter:

Code: Select all

FOR n=0 TO 1: PLOT 249-n,63+l: DRAW 0,n-57-l: DRAW n+n-248,0: DRAW 0,163: DRAW 247,0: DRAW 0,-n-57-l: NEXT n
User avatar
Spud
Manic Miner
Posts: 372
Joined: Sun Nov 12, 2017 8:50 pm
Contact:

Re: I've made a one liner - called Line

Post by Spud »

Great game, managed to get to level 15 so far.

Probably the best Speccy release this year. (It is the only one I've played though :P)
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

Replace this:

Code: Select all

READ p,q,e,l,d$: ... POKE q,65: ... DATA 23620,p+73,21,1,"//"
with this:

Code: Select all

READ p,e,l,d$: ... POKE p+73,65: ... DATA 23620,21,1,"//"
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

To backtrack a bit...
Einar Saukas wrote: Tue Jul 30, 2019 5:23 pmDon't use parenthesis unless really necessary. For instance, you can save 2 characters replacing...
This is original code from 1996 which I had missed. :oops:
Einar Saukas wrote: Tue Jul 30, 2019 5:23 pmThis way, users would be able to play the game using whatever key they prefer.
This is a great improvement because it means the game no longer needs instructions. To cover the only remaining non-intuitive aspect, I had wondered about putting LEVEL x/20 at the top left, to make it clear that there is a goal, but in my opinion it spoils the clean presentation.
Einar Saukas wrote: Wed Jul 31, 2019 7:49 pmHowever the lives indicator looks much better using INK 3
I hadn't tried that but I agree, now there's a consistent design for HUD elements. I had suspected it wouldn't be obvious what the slashes referred to, but this does look better, and it's very clear.
Einar Saukas wrote: Wed Jul 31, 2019 8:10 pmIt won't work exactly the same way, since the incidence of stars in the first and last rows, also first and last columns, will be reduced by 50%. But I think it looks even better this way. It looks good to have a higher concentration of stars closer to the center of the galaxy, not as many stars near the edge...
Yes this is better because star placement in that first and last column can spoil levels making success more dependent on luck than skill alone. This mitigates that effect.
Einar Saukas wrote: Wed Jul 31, 2019 9:40 pmHowever, gameplay works much better if the gate becomes gradually narrower after each level, instead of reducing size only once at level 10. This change will also make this code a lot shorter.
I also spent some time coding that then I realised it results in quite significant red colour clash (more so than for the obstacles). Also I saw some collision detection issues relating to the grid alignment and only checking every 2 pixels of line progression, so this deterred me from implementing. I didn't really like that the gate has to start a fair bit wider without resorting to some scaling, which would add characters.

Thanks for the awesome work on all the other enhancements. I have been able to reinstate the satisfying pattering sound of the obstacle placement and the level-up plink sound, which I think are actually quite catchy elements of the game. The only thing I'm not entirely happy with now is the death sound. I need it to be long enough you can see how you died before the screen is redrawn (without relying on a PAUSE), and I want it to be an irritating sound to contrast the nicer sounds. However, a single tone doesn't seem enough...

Latest listing:

Code: Select all

READ p,e,l,d$:
FOR d=1 TO 3:
POKE p+73,65:
BORDER 0:
CLS :
INK 2:
LET g=8*(l>9):
FOR n=0 TO 1:
PLOT 249-n,71+g:
DRAW 0,n-65-g:
DRAW n+n-248,0:
DRAW 0,163:
DRAW 247,0:
DRAW 0,-n-65-g:
NEXT n:
PRINT INK 3;"LEVEL ";l;AT 20,28+d;d$(d TO ):
INK RND*4+3.5:
FOR n=-e TO l*3:
PRINT AT RND*17+2,RND*25+4;"*":
BEEP .0001,60:
NEXT n:
INK 8:
LET y=85:
PLOT 8,y:
FOR x=5 TO 125:
LET k=4*(INKEY$<>"")-2:
LET y=y+k:
POKE p*POINT (x+x,y),35:
DRAW 2,k:
NEXT x:
LET l=l+1:
BEEP .01,20:
BEEP .01,30:
POKE p,3+34*(l=e):
BEEP .2,-20:
NEXT d:
DIM a$(32):
INK 1+5*(l=e):
FOR n=0 TO 10:
PRINT AT n,0; OVER 1;a$;AT e-n,0;a$:
NEXT n:
PRINT AT 10,n; INK 7;"GAME OVER" AND l<e;"WELL DONE" AND l=e:
DATA 23620,21,1,"//"
Download link
Last edited by patters on Wed Jul 31, 2019 11:51 pm, edited 3 times in total.
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Spud wrote: Wed Jul 31, 2019 9:43 pm Great game, managed to get to level 15 so far.

Probably the best Speccy release this year. (It is the only one I've played though :P)
Thanks. High praise indeed :)
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

patters wrote: Wed Jul 31, 2019 11:04 pm
Einar Saukas wrote: Wed Jul 31, 2019 9:40 pmHowever, gameplay works much better if the gate becomes gradually narrower after each level, instead of reducing size only once at level 10. This change will also make this code a lot shorter.
I also spent some time coding that then I realised it results in quite significant red colour clash (more so than for the obstacles). Also I saw some collision detection issues relating to the grid alignment and only checking every 2 pixels of line progression, so this deterred me from implementing.
Both problems can be solved also replacing this:

Code: Select all

FOR x=5 TO 125
with this:

Code: Select all

FOR x=5 TO 124
Now you will only get a single pixel of color clash at the gate at most, for a brief moment. It's much less noticeable than the color clash you already have whenever the line passes close to a star. Since you cannot completely avoid color clash in this new version anyway, I don't think it's worth it to sacrifice gameplay just to avoid one more case of color clash.

I wrote "sacrifice gameplay" because I think the game looks much more exciting when the gate gets gradually narrower after each level. Instead of 9 levels with a large gate, followed by 11 levels with a small gate. However that's just my opinion. It's your game so it's your decision!

patters wrote: Wed Jul 31, 2019 11:04 pm This is a great improvement because it means the game no longer needs instructions. To cover the only remaining non-intuitive aspect, I had wondered about putting LEVEL x/20 at the top left, to make it clear that there is a goal, but in my opinion it spoils the clean presentation.
Again, it's non-intuitive because many players won't read the instructions, they will assume the game doesn't have an ending so they won't persevere to finish it.

If the gate gets narrower after each level, this will provide a clear goal for them, without the need for explanations.

patters wrote: Wed Jul 31, 2019 11:04 pm I didn't really like that the gate has to start a fair bit wider without resorting to some scaling, which would add characters.
It will make the game more accessible in the beginning, and more challenging in the end. I don't think that's a bad thing.

patters wrote: Wed Jul 31, 2019 11:04 pm Thanks for the awesome work on all the other enhancements.
You are welcome!

patters wrote: Wed Jul 31, 2019 11:04 pm I have been able to reinstate the satisfying pattering sound of the obstacle placement and the level-up plink sound, which I think are actually quite catchy elements of the game. The only thing I'm not entirely happy with now is the death sound. I need it to be long enough you can see how you died before the screen is redrawn (without relying on a PAUSE), and I want it to be an irritating sound to contrast the nicer sounds. However, a single tone doesn't seem enough...
I'm sure we can save a few more characters, so you can add a second BEEP. How much more space do you need?

To save a few more characters, replace this:

Code: Select all

READ p,e,l,d$: ... FOR n=0 TO 1: PLOT 249-n,63+l: DRAW 0,n-57-l: DRAW n+n-248,0: DRAW 0,163: DRAW 247,0: DRAW 0,-n-57-l: NEXT n: ... DATA 23620,21,1,"//"
with this:

Code: Select all

READ p,l,d$: ... FOR e=19 TO 20: PLOT 268-e,63+l: DRAW 0,e-76-l: DRAW e+e-286,0: DRAW 0,163: DRAW 247,0: DRAW 0,-e-38-l: NEXT e: ... DATA 23620,1,"//"
User avatar
Einar Saukas
Bugaboo
Posts: 3070
Joined: Wed Nov 15, 2017 2:48 pm

Re: I've made a one liner - called Line

Post by Einar Saukas »

Here's how to save another 12 characters. Replace this:

Code: Select all

READ p,l,d$: ... POKE p+73,65: ... PRINT ... AT 20,28+d;d$(d TO ): ... POKE p*POINT (x+x,y),35: ... POKE p,3+34*(l=e): DATA 23620,1,"//"
with this:

Code: Select all

LET l=1: ... POKE 23693,65: ... PRINT ... AT 20,28+d;"//"(d TO ): ... POKE 23620*POINT (x+x,y),35: ... POKE 23620,3+34*(l=e)
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

Wow, more great optimisations. I almost suspect you'll be able to halve the size of this listing if you keep looking. :lol:

Using another loop to define "e" like that at the beginning is ingenious. Also in retrospect I have no idea why I defined d$ instead of slicing the string directly.

I'll do some more experimenting with the gate. The other thing about the gradual progression design is that the game difficulty will decrease, and I currently consider it to be just right: clearly difficult, but tantalisingly possible. Still, it's nothing that can't be tuned...
hikoki
Manic Miner
Posts: 576
Joined: Thu Nov 16, 2017 10:54 am

Re: I've made a one liner - called Line

Post by hikoki »

Nice!!
It's fun when you bump into the gate :x I agree that would be fun to see it narrowing sooner in the game.
Suggestion: put a max number of keystrokes on every screen. I think it'd be fun to see this number decreasing.
User avatar
patters
Manic Miner
Posts: 467
Joined: Thu Apr 11, 2019 1:06 am

Re: I've made a one liner - called Line

Post by patters »

I think Einar's example use of the unmodified variable 'l' for the gate sizing results in a gate that starts too wide (making it too easy for too long) and ends with it too narrow for my liking. I prefer to use 'l/2' which starts the gate 4 pixels wider than before (36px compared to 32px). It shrinks by two pixels every second level, finishing at 16px for level 20 (the previous small size).

I've had to resort to:

Code: Select all

LET g=INT (l/2)
because otherwise 0.5 rounding up makes a mess of the DRAW operations. Is there a better way?
I can't stop play testing this - I did just complete it again, very satisfying :)
Post Reply