Log In  


Cart #55585 | 2018-08-24 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

Many of the games in PICO involve a player shooting at a target. I mention strafing several times and I think some of you are not understanding what I mean.

Here is a good example of strafing. Hold down the firing button and you will see that you fire in the last direction you moved.

HOWEVER, as long as the firing button is held, despite moving in any other direction the firing direction remains the same - until you let go of the firing button. This is called STRAFING.

This makes it a lot easier to avoid incoming enemy fire yet still continue to fire in the same direction at your desired target.

This example also demonstrates staggered shooting. If you hit the button manually, you can fire faster than if you just hold it down. This is optional but may reward the player to have quicker response by manually hitting the button rather than relying on autofire.

This program also shows effectively how to use three fairly advanced commands:

+ ADD
+ DEL
+ FOR (variable) IN ALL / END

Using these 3-statements you can create any number of moving elements that vary in number. Quite useful for shooting multiple shots (as in this example) and any other items that needs to be spawned in which you don't need to keep track of the total number in use.

HOPE THIS HELPS !



If it is intended to help newbie devs, suggest to:

  • use _init/_draw/_update to demonstrate separation of game state/game display
  • use functions to separate core elements (why do we have bold printing in the middle of the thing)
  • use ‘local’ as much as possible to pin variable in function scope
  • use a vector {x=..,y=..} for firing directions
  • use map instead of drawing the same sprite in a game loop

Well now, Freds. Don't get yourself all het up.

Not everyone is going to use _INIT, _DRAW, _UPDATE. I certainly seem to get by without them and have for years.

All variables in MAIN() are expected to be global. Only reason it's listed as a function is PICO refuses to recognize functions at the end of a main program.

My way of getting around this.

I used a lookup table for shooting directions so - I don't know what you mean by vector. Don't need SIN/COS for simple 90 degree angles.

And I didn't want to use MAP, it was a simple single character pattern to overlay. If it were something complex, fine, I might've.

Also I learned quite some time ago that PICO is fast. I mean - it runs like a stink !

Many of the methods you mentioned are fine if you're running in an OS stacked for speed. PICO lacks none so you can definitely get away with the dirtiest of programming, just like Borland's Turbo Pascal from years ago. :)

I remember writing whole libraries in that language which manipulated the screen one pixel at a time and never even resorted to using the inboard plot, oval, rectangle, sprite, or line - because it ran so very quickly.

Good times ...


It's not PICO-8 refusing to recognize undeclared functions, it's just how Lua works. Most languages are like that.

That's one nice thing about using the built-in _init()/_update()/_draw() paradigm. A complete pass over the code is made before those callbacks begin to get called, so you can declare stuff anywhere and, by the time something actually tries to call it, the declaration will have been parsed.

Also, that init/update/draw mechanism is set up to handle some things cleanly for you. You can do it yourself, of course, but you'll just be re-inventing the wheel pointlessly. It handles frameskipping if you go over CPU budget, for instance. Code written your way will slow down rather than handling it gracefully. As I said, you can write that code manually (and I have many times in my career), but it's really not a good use of time, not to mention costing you tokens you need not spend.

I agree with freds72, in that as much as I'm certain your intentions were the best and I approve of your enthusiasm for PICO-8, I would not suggest this as example code for a PICO-8 newbies. Veering off of the standard pattern is, at best, for advanced users. It's more of a demoscene thing to ignore the OS/kernel and roll your own.


Well alright ...

I did write my very FIRST program using _update() just a moment ago. And -- the results weren't favorable for me.

I guess my main problem with this method is, I don't code like that. I'm not seeing a use for a program that draws and updates invisibly in the background.

I want my code only to update when it hits FLIP() and no other time.

It also requires me to focus coding specific TYPES of events for these system functions. And I don't do that either.

I like to have my code all sequential, all running neatly and in order.

I know I'm not the only one that codes like this. Back in the GFA scene, no-one used functions like that and we all just wrote and ran our spaghetti code.

It was heavenly. :)

And no, I really wasn't expecting someone to pick at my source code. The executable was to show game writers the importance of STRAFING and staggered shooting.

I know I wrote a bit about the difference between BTN() and BTNP() as well. There are quite a few really good platformers out there that suffer because they use BTNP().

I could write a demo cart to show the difference on that too - but I thought I did already.

Anyways, you don't need to look at my bad coding to see an important element of game design.


I think the main thing Felice was trying to say is that since Pico-8 already handles those things gracefully. By rolling your own you're just costing tokens, which are precious, outside of small examples like so, and speed which, is for the most part, irrelevant unless you're doing crazy stuff.

It's pretty common place for new users around here to come and just search "examples" or similar and learn from them as they go along. So I think, while you may not have intended for other uses to look at your source, it's sort of a "position of power" sort of thing, as you are an advanced coder with lots of experience under your belt, these other people are going to look up to you and your example because outside of obfuscation there's no manner of closing your source. So it's inevitable newbies will come along and try to figure out what's going on. Unless you meant Felice picking at your code, in which case I'd put money that they never even looked at it. I know how they tend to be. @Felice, hey you. ;p

I agree with you in that there's no reason for examples and small write ups to take full advantage of the built-in Pico-8 structure. I also agree that there's definitely more than one way to go about skinning a cat, or coding one in this case. I'm actually much like you, I come from GW BASIC roots as well as TI BASIC for my starting languages and quickly moved to messing with assembly directly. I know the satisfaction of having a neatly sequenced piece of code execute and knowing exactly where it's traveling at all times. Also, just sort of a "did you know?" moment, but I haven't looked at your coding at all, but as someone who appreciates this structure did you know Pico-8 supports labels and jumping to them? Fun fact if you didn't know! :) But I digress, I think the main concern is new users coming in and learning things one way when the standard is another. Of course they are free, as are you, to choose any manner of programming style they wish, but they as new users may not immediately understand the value which is to be gained through using the default structure nor have a full appreciate of freedom of structure that comes along with your style.

It took me a long while to get used to Pico-8's default functions but once I got the hang of it, I realized I could use a beautiful mix of Pico-8's structure yet still keep that IMPERATIVE feeling alive and save tokens and speed to boot!

Also, my most important point here:
[quote]Anyways, you don't need to look at my bad coding to see an important element of game design.[/quote]

Your coding is not bad.
I know that, you know that, Felice, Fred, and anyone who is worth their weight in salt knows that.
Maybe it's just sarcasm but I'm quick to call out a falsity when I see one and this is definitely one.
You got mad skillz.
I don't think anyone is here to have beef with that, I think they just wanna help cater to a universal sort of idea for new users.

While it's not your responsibility to write your code or examples with new users in mind, many of us love to provide our insight and experiences with the platform for everyone coming new to the pico scene.

I believe that's one of my favorite things about this bbs there's never a lack of information or help for new users, there's tons of people who are all very talented and well versed in many disciplines scattered across the board. For a newbie to Pico-8 and even programming in general, I think this place is a gold mine and definitely where you should be right now if you're looking to get into game development!

EDIT: For the record, labels are defined as ::lable_name:: and can be jumped to with "goto lable_name."


Okay, this is my thread so I can derail it if I like.

Let me say the first thing coming out of my head.

"I DON'T GET IT."

No, really.

Let's take a full game I wrote, that Haunted House thing. Let's try to put it to those 3-functions. Those dreaded _update(), _draw(), and _init()

Okay, taking a deep breath

First off, let me see if I know what these functions do, because I could be wrong. I really could. Probably am since I never use them.

Without looking I would say UPDATE() updates the screen when it changes. DRAW() does the same, so already I'm wrong here. :)

And INIT(). Well that's just silly. It just runs one time. You can get the same results from making your own custom function and running it once.

Back to the Haunted House.

When it starts, I have text appear on the screen, little copyright, little warning (for epilepsy as it really does a lot of flashing), and then go to my logo.

I'm - I can't see this - I can't see how using a function like update() or something is going to help.

If I'm reading this correctly, I would need to create unique code inside the update() function that handles graphics. And - that's with the understanding it's running I guess, at 60fps or something.

And that's a forced timing I don't want, that or 30fps. I want to draw what I want to draw when I want to draw. And I don't want to release FLIP() until I'm darned good and ready.

Here's a problem I see with update(). Suppose we're going old-school. I want to move a spaceship from the bottom to the top of the screen.

The really old way is using XPLOT. Not needed here, but let's plot the ship normally, with SPR(). Okay, now I need to erase it too so I can using RECT() or something to erase it.

Who is not to say that the infernal update() routine is going to show the display (30fps you remember) RIGHT when the ship has vanished.

Now if I was left to my own devices, I would plot the ship, use FLIP() to show it, then do absolutely everything else, including removing it from view so it can move up slightly.

With update() you can't do this. Now I know you guys are wizard at this but my brain is just not going to be able to figure out the timing invoved in having my ship appear or not appear according to a vicious clock.

Am I correct so far, CD ?

And yes, I know about GOTO, I appreciate your info on it.

I just - well, I've always been worried it would mess with the stack or something if I used it to pull out of a deep repeat/ or for/ routine and forced it to go places from there.

You could chomp up your stack in Turbo Pascal causing the computer to crash doing this, so for the most part if I need a loop, I do make use of REPEAT/Until forever (and forever, I know, is NIL, it just makes it easier in my head to understand).


That's not how _update() and _draw() work.

If you spend more time reading the docs or other people's carts' source code, you'll do yourself a lot of good. The user-created wiki is also pretty useful.

It's fine to do things your own way, of course, but you're really hamstringing yourself never to even learn how to do it before you discard it out-of-hand. I find that, in life, when everyone else is doing something a different way from how I like to do it, it's because I haven't recognized why their way is appealing.


No, I don't want to eat broccoli, Felice. No don't tell me they're little trees. Those poor trees - they ...

???

No ? That's not going to work ? Really. SIGH

You know, I've had this same problem in music. Me ? I write music, rather good at that on a piano. Got a silver award one time for best original compositions. But do I know how to read sheet music ?

Not a scratch, instead I developed my own notation that uses colors to represent length and they are absolute positioned on a 90-degree tilted piano.

I wrote a program years ago on Commodore Amiga called, "Prism Player." Prism because of the colors.

It was pretty neat. It allowed me write out all my music and easily at that. When I took music in college, I brought a little electronic keyboard.

My instructor, big smile on his face came over and said what do you have here.

I said, my piano. He chuckled. Asked if I knew the names of the keys, and pointed to one.

I said, absolutely, that is the 3rd of the black 4th.

He grinned wider. "You made your own notation didn't you."

I nodded.

And, well, you have to see the video to understand:

https://youtu.be/hspNaoxzNbs

Yes, he was just like that. Red, mad, and furious that I wouldn't learn "his" way, which I later learned was "their" was, which I later LATER learned was the "ONLY WAY." And yes, I felt a lot like that bird. I knew I could do music, but was shunned by the class I took because I wouldn't do it the "right" way.

SIGH

Today I'm told I don't type correctly. I tilt the keyboard at a 45-degree angle in my lap and use only 4-5 fingers to type. Yet when tested for a job I type about 135wpm with less than 1% errors. Got me some good secretarial work back then. Even wrote a book about working for the government - strange people they are.

But if there is one thing I am is a master, I mean an absolute WIZARD at, and that is finding shortcuts to anything. I am born and bone lazy and I don't think that's going to change. Once I find a shortcut in programming, or write one, it is very hard to loosen my grip on it later.

And, I have always seen _update(), _draw(), and _init() as NOT being shortcuts, in fact being quite the opposite. Long-hair stuff, the kind of fluff that gets caught in the back of your throat until you finally hock up a hairball.

And so in theory, maybe these functions are.

However, I am not deaf. Not yet ... :)

I will take PICO class one-zero-one and see how to write a program the "correct" way from scratch. I will begin HERE:

http://pico-8.wikia.com/wiki/GettingStarted

But I don't have to like it ...


Y'know, for tutorial stuff, I might actually suggest Krystman's lengthy Let's Make Breakout in PICO-8! series.

It's definitely done for absolute beginners, so oldtimers like us can sorta kick back and feel superior for the first handful of episodes while the other viewers get up to speed, but he does drop a lot of good little nuggets along the way.

It's a pretty big time investment, so you might want to turn playback speed up to 1.5X or so, but he's a pretty chill guy who really takes his time to explain what he's doing, taking the viewers all the way from nothing to a full-fledged Arkanoid-tier breakout game.

YMMV. It might be too-too-tutorial. I just figured it was worth pointing out in case you took a liking to it. I'm pretty crap at teaching people how to write games, so I usually notice it when someone else is doing a better job than I can.

PS: Gotta admit, I've always found musical notation to be very archaic-looking and cobbled-together-and-built-upon-over-many-lifetimes. But I'm not a musician, so I don't know squat really. I think it's just one of those things where, even if it was designed hundreds of years ago with insufficient forethought, it's nice to have a common language to speak to other musicians through. Kinda like the QWERTY layout is actually pretty terrible (and deliberately so) but, at least once you know it, you can use most any keyboard in a QWERTY region of the world.


What are the odds ?

I just finished that series, Felice, about Breakout. Ran at double-speed. I got really frustrated halfway through and took his code and wrote it the way I would, about 90% smaller - in a comment. I'm sure he'd like me to talk a long walk now too. :)

Okay. Let's face some facts. I now understand _init(), _draw(), and _update(), at least as far as I want to.

Here's the POP test. No cheat sheet. Begin ... now !

QUESTION ONE: What does "_init()" do.

This system function will be run first in PICO-8. Why it exists I have no idea. You can certainly write your code either outside a function or inside one you plan to execute just run once. Redundant redundant redundant.

Answer: You are correct but you're also taking a very bad attitude about this.

Reply: Yes I am. Sue me. Next question.

Question TWO: What does the "_draw" function do ?

The "_draw" function is called every time the screen is drawn to. You are to put all your drawing commands in here. I ALSO see this as redundant as you can use FLIP() in any part of your code to accomplish the same results.

I also see this as being a bad function in that it forces you to write all your output routines in one area, whereas it's much easier to draw to the screen on the fly as you like according to the point and method your code is presenting at the time.

Answer: You are correct. Once again you - you really don't like these questions, do you ?

Reply: It's not that the questions are bad, it's just even after watching all of those lengthy breakout tutorials - I see NO reason at all to start using these functions in any capacity - except for writing interrupt debugging libraries - that might be something, but for later.

In any case, as it is, it would force me to code in such a way that I could not for the life of me see the project I was working, not in easy-to-understand sequential fashion.

In fact, at this point in my learning experience, I would actually be glad if someone DID look at my source codes, closely, and see their way to not wanting to use _update(), _draw(), or _init() to get their job done if they think about solving problems and coding issues sequentially as I do.

QUESTION THREE: What does "_update()" do ?

Depending upon whether you are using "_update()" or "_update60()" you get different results.

In any case, this is the code that is run every 30- or 60-frames per second. Once again, a very bad idea as you may not want to be running all of your code at every 30- or 60-frames per second.

I understand the "meat" of a program goes here, but I would find it difficult if not impossible to write a "switch" inside there to change according to what is being run and what is not.

Answer: PROVISIONALLY CORRECT.

Anything else ? No, that'll do it.

. . .

No I think at this point I'm more interested in learning professional and expert recursion coding. Also extended variable types and pointers. Advanced techniques involving bit shifting and mathematical and complex methods for solving difficult logical problems.

That is something that I would definitely find useful to learn for PICO.

. . .

As for musical notation and language, Felice ? Yep. Leave me to my own devices and I'll rewrite the English alphabet and create my own verbal and written language that no-one can understand or speak. :)

Oh, and just so this comment isn't a total bomb for everyone else, here is a copy of TC's "Cheat-Sheet" for PICO-8 which I actually found quite helpful and informative.


/me mutters something about horses and water



[Please log in to post a comment]