I was working on a little library awhile ago called Pixler for the TI-83/84s. Pixler could be used to easily to certain basic 2D graphical things, like draw pixels, draw lines, and draw squares.

I'm now updating my Pixler library to Pixler3D.
Pixler3D will give you the ability to draw points in three dimensions. It will also have subroutines to draw planes and rectangular prisms.

Note that all of these 3D shapes are wireframe.
They're not filled in, because if you did that, it would just be all black.
Also, since I don't have the TI-84 Color, I haven't ported this to it yet. I will do so once I get it, though. And I plan to get one near the end of next month.

I know how to do rotations in most other languages, but with z80 Assembly, I'm sure to have trouble with rotations, so I might not release that part for awhile. I do plan on doing them, though. I'm only a high school student, so cut me some slack.

So far, though, I have a 3D cube working. It needs some more work and stuff.

When you define points, I made a subroutine called "DefinePoint" and "DefinePointISO". "DefinePoint" creates points with a sort of perspective 3D. By this, I simply mean that the greater the depth of the point, the more it bends towards the center of the screen. This gives an illusion of 3D, like you would see in most 3D games. If the depth increases, this also results in the shape appearing to grow smaller, as if it's getting farther away. "DefinePointISO" gives you isometric 3D. The greater the depth, the more the cube is translated up and to the left. It does not curve towards the center. This is 3D you would see in most isometric games, like RTS games.

Here is an example of rectangular prism:


Note that it does not flicker and runs much smoother on the actual calculator than the emulator that I recorded that GIF on.

Currently, creating a cube would be done like this:


Code:
bcall(_GrBufClr)

ld a, 0
ld (_pixler_cube_x), a
ld (_pixler_cube_y), a
ld (_pixler_cube_z), a

ld a, 10
ld (_pixler_cube_width), a
ld a, 10
ld (_pixler_cube_height), a
ld a, 10
ld (_pixler_cube_depth), a

call defineCube
call drawCube

bcall(_GrBufCpy)

Note that (0,0,0) is not the top-left corner of the screen, but the center of the screen.

Anyways, yeah. That's one thing I'm working on.
I'll post the ".inc" file once I get it all nice and generally working.
I'll also post it as an environment variable for Mimas in which you could include into your Mimas programs.

That's basically how it's going to work.
Very impressive!

Im a very interested in 3D engines, particularly on z80 calcs. I think this is a great start.

Do you have any plans to use this library for a project or game?
Wow, that's really cool! I hope you post more with it. Like tr1p asked, are you planning on making any games?

As a side note, which emulator are you using? Something like jsTIfied or Wabbitemu might suit your needs better.
tr1p1ea wrote:
Very impressive!

Im a very interested in 3D engines, particularly on z80 calcs. I think this is a great start.

Do you have any plans to use this library for a project or game?


Not in particular.
I had a couple ideas.

If you've seen my PC game I'm working on, I was thinking of something similar to that.
Or, if you've seen my RPG game for the TI-83/84, I might make another RPG like that. Accept this time, I would have a 3D dungeon rather than the simplistic 2D one depicted in that game.
I notice you ran that with the Asm( command, which suggests to me that you're using the _ILine command. Is that correct? I have found _ILine to be very slow; you might be better off with the several-times-faster fastline routine in Doors CS 7.
merthsoft wrote:
As a side note, which emulator are you using? Something like jsTIfied or Wabbitemu might suit your needs better.


I was using the TI-83 Flash Debugger.
jsTIfied seems to run slow for me, but it's what I mostly use since I do most of my work on my Chromebook.
I guess since I speed up the GIF anyways, it doesn't matter.

I've never tried Wabbitemu, except for the DS Homebrew port.

KermMartian wrote:
I notice you ran that with the Asm( command, which suggests to me that you're using the _ILine command. Is that correct? I have found _ILine to be very slow; you might be better off with the several-times-faster fastline routine in Doors CS 7.


I actually originally wrote my own line routine.
But it was glitchy at times and I so I switched to _ILine until I can fix it.
Amihart: jsTIfied will take screenshots that display at "realtime" speed, even if you're on a slow computer, so it will give us a pretty accurate view of how fast the program is. Smile As its coder, I certainly recommend you check it out, and I've been making strides towards speeding it up.

Quote:
I actually originally wrote my own line routine.
But it was glitchy at times and I so I switched to _ILine until I can fix it.
Then I'd certainly recommend you give my fastline a try. Not to mention that things like iFastCopy are significantly faster than grbufcpy_v.
Kerm is correct, you should see a decent speed improvement by switching those routines over.
KermMartian wrote:
Amihart: jsTIfied will take screenshots that display at "realtime" speed, even if you're on a slow computer, so it will give us a pretty accurate view of how fast the program is. Smile As its coder, I certainly recommend you check it out, and I've been making strides towards speeding it up.


Oh, nice, I'll try that out.
Also, since you're working on jsTIfied, would you mind porting jsTIfied to a packaged desktop app via Chrome? Basically, through Chrome, you can take web-based applications and package them into desktop applications that run offline. It's designed to be pretty easy so I'm sure it wouldn't take too long.

I know that's sort of a strange request, but I would like to use jsTIfied offline. And packaging it would allow me to install it onto all of my computers and use it offline.

You can also put it on the Chrome Web Store so anyone can install it just by going to the page and clicking it.

I could also explain how you can do so if you are unfamiliar with it.

I've been meaning to request for someone who's working on this to do so.
I'm assuming the lack of response means "no".
Anyways, once I finish the library, I'll update it for Doors CS for optimization.

I'm also changing some things.
Now, instead of storing everything in labels like above, you use registers. Such as, to draw a cube, now you do this:


Code:
    ld b, 0
    ld c, 0
    ld h, 0
    ld d, 10
    ld e, 10
    ld l, 10
    call DrawCube


BC holds the X and Y, DE holds the width and height, and HL holds the Z and depth.
I also made the "DefineCube" subroutine call on the "DisplayCube" subroutine automatically, and changed the label to "DrawCube". This way, you only have to call one of them and not two.

Here is the library so far if you want to download it and try it.
If you're using Mimas, add the file as a library in order for it to work.
If you're using any other z80 Assembly, just throw a "#include" in there somewhere.

Here is a demo of it so far:

Code:
#include    "ti83plus.inc"
#define     progStart   $9D95
.org        progStart-2
.db         $BB,$6D

main:
    bcall(_RunIndicOff)
    bcall(_GrBufClr)
   
    ld a, (__x)
    ld b, a
    ld a, (__y)
    ld c, a
    ld a, (__z)
    ld h, a
   
    ld a, (__w)
    ld d, a
    ld a, (__h)
    ld e, a
    ld a, (__d)
    ld l, a
   
    call DrawCube
    bcall(_GrBufCpy)
   
    bcall(_GetCSC)
    ld (tmpk),a
    ld a, (tmpk)
    cp skClear
    ret z
    ld a, (tmpk)
    cp skRight
    call z,MoveRight
    ld a, (tmpk)
    cp skLeft
    call z,MoveLeft
    ld a, (tmpk)
    cp skUp
    call z,MoveUp
    ld a, (tmpk)
    cp skDown
    call z,MoveDown
    ld a, (tmpk)
    cp skSub
    call z,MoveIn
    ld a, (tmpk)
    cp skAdd
    call z,MoveOut
   
    ld a, (tmpk)
    cp sk1
    call z,ExpandWidth
    ld a, (tmpk)
    cp sk2
    call z,ExpandHeight
    ld a, (tmpk)
    cp sk3
    call z,ExpandDepth
   
    ld a, (tmpk)
    cp sk4
    call z,DecreaseWidth
    ld a, (tmpk)
    cp sk5
    call z,DecreaseHeight
    ld a, (tmpk)
    cp sk6
    call z,DecreaseDepth
   
    jp main
   
    ret   
   
MoveRight:
   ld a, (__x)
    add a, 1
    ld (__x), a
    ret
       
MoveLeft:
   ld a, (__x)
    sub 1
    ld (__x), a
    ret
       
MoveUp:
   ld a, (__y)
    sub 1
    ld (__y), a
    ret
       
MoveDown:
   ld a, (__y)
    add a, 1
    ld (__y), a
    ret
       
MoveIn:
   ld a, (__z)
    add a, 1
    ld (__z), a
    ret
       
MoveOut:
   ld a, (__z)
    sub 1
    ld (__z), a
    ret
       
ExpandWidth:
   ld a, (__w)
    add a, 1
    ld (__w), a
    ret
       
DecreaseWidth:
   ld a, (__w)
    sub 1
    ld (__w), a
    ret
   

ExpandHeight:
   ld a, (__h)
    add a, 1
    ld (__h), a
    ret
       
DecreaseHeight:
   ld a, (__h)
    sub 1
    ld (__h), a
    ret
   

ExpandDepth:
   ld a, (__d)
    add a, 1
    ld (__d), a
    ret
       
DecreaseDepth:
   ld a, (__d)
    sub 1
    ld (__d), a
    ret
   

tmpk:
   .db 0

__x:
   .db 0
__y:
   .db 0
__z:
   .db 0
__w:
   .db 10
__h:
   .db 10
__d:
   .db 10
   

#include "pixler.inc"


If you don't know which calls take which inputs, just look at the comment at the top of the "pixler.inc" file. Or read it here:


Code:
;--------------------Pixler----------------------;
; Graphic Subroutines                            ;
;                                                ;
;  DrawPoint                                     ;
;    Inputs:                                     ; 
;      B                                         ;
;         • specifies the X coordinate of the    ;
;           of the pixel or sprite to draw       ;
;      C                                         ;
;         • specifies the Y coordinate of the    ;
;           of the pixel or sprite to draw       ;
;      Outputs:                                  ;
;        Bit changed in PlotSScreen              ;
;                                                ;
;  DrawSprite                                    ;
;    Inputs:                                     ; 
;      B                                         ;
;         • specifies the X coordinate of the    ;
;           of the pixel or sprite to draw       ;
;      C                                         ;
;         • specifies the Y coordinate of the    ;
;           of the pixel or sprite to draw       ;
;      DE                                        ;
;         • zero-terminating bytes to represent  ;
;           the sprite to be drawn               ;
;      Outputs:                                  ;
;        Bits changed in PlotSScreen             ;
;                                                ;
;  DefinePoint                                   ;
;    Inputs:                                     ;
;      B                                         ;
;         • specifies the X coordinate of the    ;
;           pixel to define                      ;
;      C                                         ;
;         • specifies the Y coordinate of the    ;
;           pixel to define                      ;
;      A                                         ;
;         • specifies the Z coordinate of the    ;
;           pixel to define                      ;
;    Outputs:                                    ;
;      B                                         ;
;         • the true X to be drawn onto the      ;
;           screen with DrawPoint                ;
;      C                                         ;
;         • the true Y to be drawn onto the      ;
;           screen with DrawPoint                ;
;                                                ;
;  DrawRect                                      ;
;    Inputs:                                     ;
;      B                                         ;
;         • specifies the X coordinate of the    ;
;           rectangle to be drawn onto the       ;
;           screen                               ;
;      C                                         ;
;         • specifies the Y coordinate of the    ;
;           rectangle to be drawn onto the       ;
;           screen                               ;
;      D                                         ;
;         • specifies the width of the           ;
;           rectangle to be drawn onto the       ;
;           screen                               ;
;      E                                         ;
;         • specifies the height of the          ;
;           rectangle to be drawn onto the       ;
;           screen                               ;
;    Outputs:                                    ;
;      Bits changed in PlotSScreen               ;
;                                                ;
;  DrawCube                                      ;
;    Inputs:                                     ;
;      B                                         ;
;         • specifies the X coordinate of the    ;
;           plane to be drawn onto the screen    ;
;      C                                         ;
;         • specifies the Y coordinate of the    ;
;           plane to be drawn onto the screen    ;
;      D                                         ;
;         • specifies the width of the plane     ;
;           to be drawn onto the screen          ;
;      E                                         ;
;         • specifies the height of the plane    ;
;           to be drawn onto the screen          ;
;      H                                         ;
;         • specifies the Z coordinate of the    ;
;           plane to be drawn onto the screen    ;
;      L                                         ;
;         • specifies the depth of the plane     ;
;           to be drawn onto the screen          ;
;    Outputs:                                    ;
;      Bits changed in PlotSScreen               ;
;                                                ;
;                                                ;
; Other Subroutines                              ;
;  DivAByB                                       ;
;    Inputs:                                     ;
;      • A - number to be divided                ;
;      • B - number to divide by                 ;
;    Ouputs:                                     ;
;      • A - the result                          ;
;      • B - the remainder                       ;
;  MulHLByA                                      ;
;    Inputs:                                     ;
;      • HL - number to multiply                 ;
;      • A  - number to multiply by              ;
;    Outputs:                                    ;
;      • HL - the result                         ;
;  GetRand                                       ;
;    Inputs:                                     ;
;      • A - maximum number                      ;
;    Outputs:                                    ;
;      • A - random number                       ;
;  SetSeed:                                      ;
;    Inputs:                                     ;
;      • A - number of the random seed           ;
;    Outputs:                                    ;
;      • None                                    ;
;  AToString                                     ;
;    Inputs:                                     ;
;      • A  - integer to convert to a string     ;
;    Outputs:                                    ;
;      • HL - location of converted string       ;
;                                                ;
;                           by Amelia Hartman    ;
;--------------------Pixler----------------------;
Nice job!
Seems like there is tons of 3D-dev for the z80 these days Smile
Sorunome wrote:
Nice job!
Seems like there is tons of 3D-dev for the z80 these days Smile


There is? Surprised
All I've seen is zDoom. I didn't know there was a lot of development already for something like this.
amihart wrote:
I'm assuming the lack of response means "no".
Anyways, once I finish the library, I'll update it for Doors CS for optimization.
No, the lack of response just means I didn't get to respond to the topic. Smile Thus far I've been hesitant to package jsTIfied in any way other than online, as it changes rapidly, and any packaged version would be quickly out of date. If you load the emulator in a tab and then go offline, it will continue to work properly. The only things that won't work are exporting files and taking screenshots. Smile

Quote:
I'm also changing some things.
Now, instead of storing everything in labels like above, you use registers. Such as, to draw a cube, now you do this:[snip]
Excellent, that seems like a logical change to me. Smile Also, you can save a few byte by loading bc, hl, and de instead of b, c, h, l, d, and e:
Code:
 ld bc,(0*256)+0
ld de,(10*256)+10
ld hl,(0*256)+10
KermMartian wrote:
amihart wrote:
I'm assuming the lack of response means "no".
Anyways, once I finish the library, I'll update it for Doors CS for optimization.
No, the lack of response just means I didn't get to respond to the topic. Smile Thus far I've been hesitant to package jsTIfied in any way other than online, as it changes rapidly, and any packaged version would be quickly out of date.


I think it would be worth it, though. It shouldn't be too hard at all, and it will turn your emulator into one for the desktop, like Tilem.

How I solved that out-of-date problem for my game I'm developing is I wrote a couple "try...catch" statements.
Since package applications are nearly identical to the ones in the web browser, adding a couple "try...catch" statements could allow it to determine whether it's in the browser or the application, and execute code as so.

Such as this section:

Code:
if (launch) {
        try {
           chrome.app.window.create('play.html#'+text, {
              'bounds': {
                 'width': 1200,
                 'height': 800
              }
           });

        window.open("", "_self", "");
        window.close();
        } catch (e) {
           window.location = "./play.html#" + text;
        }
    }


In my game, when you press the "Create Dungeon", it first tries to create a new window. If it can't, that means it's probably being ran in the browser and isn't packaged, so it ditches that and just changes the browser window's location.

The idea isn't to port your code every single time. It's to change your code so that it works both ways.

Then, you don't have to worry about ever adjusting the code again to be packaged. Whether you run the file on the web server or as a packaged app, both ways it will run properly without ever having to port it again. Just, as you upload the new files to Cemetech, you also zip the files and upload the package as well.

Quote:
If you load the emulator in a tab and then go offline, it will continue to work properly. The only things that won't work are exporting files and taking screenshots. Smile


Yeah, but I close tabs a lot. It's more convenient to load up something else.

Quote:
IAlso, you can save a few byte by loading bc, hl, and de instead of b, c, h, l, d, and e:
Code:
 ld bc,(0*256)+0
ld de,(10*256)+10
ld hl,(0*256)+10


Interesting, never thought of that.
Sorunome wrote:
Seems like there is tons of 3D-dev for the z80 these days Smile

Really? Didn't know, glad to hear it! So we should have a 3D Minecraft clone soon (which is possible). Smile

Also, Amihart, your 3D program here looks excellent. Even if the screenshot is like nothing I've ever seen before, and is somehow reminiscent of an old TV. Very Happy
Quote:
Also, Amihart, your 3D program here looks excellent. Even if the screenshot is like nothing I've ever seen before, and is somehow reminiscent of an old TV. Very Happy


Are you referring to the blue lines and flickering?
That's from the emulator. Not really my fault. :I

CalebHansberry wrote:
Sorunome wrote:
Seems like there is tons of 3D-dev for the z80 these days Smile

Really? Didn't know, glad to hear it! So we should have a 3D Minecraft clone soon (which is possible). Smile


Because of all the people making 3D libraries, I've decided to turn mine into a different direction. Rather than being a full 3D library, it's going to be simplistic, but fast, and serve a specific purpose. Since most 3D engines people are making are probably going to have a ton of features that will slow it down, this engine is going to have specific features and be very fast.

I'm going to write easy subroutines for sprites, camera, and collision, so people can use the library to create 3D side-scrolling platformers. These are sometimes called "2.5D" platformers. I'm not going to bother with things that will slow it down, such as rotations (in which requires trigonometric functions), or "filling in" the faces of the blocks, or making ones behind others not show up.

For sprites, I'm writing three ways to draw sprites:

DrawSprite3D
DrawSprite
DrawSpriteFast

These are listed from slowest to fastest.
DrawSprite3D draws a 2D sprite in, you guessed it, 3D.
It's the same as DrawSprite, but increasing the depth makes it appear as if it's farther out.
DrawSprite simply draws a 2D sprite.
DrawSpriteFast draws a sprite very fast, but the sprite must have a width of 8 and can only move left and right in increments of 8.

Here's an example of DrawSprite:

Code:
ld b, 10
    ld c, 10
    ld hl, sprite
   
    call DrawSprite
...
sprite:
   .db 0,0,0,0,1,1,1,0,0,0,0,2
   .db 0,0,0,1,0,0,0,1,0,0,0,2
   .db 0,0,1,0,0,0,0,0,1,0,0,2
   .db 0,1,0,0,0,0,0,0,0,1,0,2
   .db 0,1,0,1,1,0,1,1,0,1,0,2
   .db 1,0,0,0,0,0,0,0,0,0,1,2
   .db 1,0,0,0,0,0,0,0,0,0,1,2
   .db 0,1,0,0,0,1,0,0,0,1,0,2
   .db 0,1,0,0,0,0,0,0,0,1,0,2
   .db 0,0,1,0,0,0,0,0,1,0,0,2
   .db 0,0,0,1,0,0,0,1,0,0,0,2
   .db 0,0,0,0,1,1,1,0,0,0,0,2
   .db 3


For DrawSprite and DrawSprite3D, you define sprites like that.
"0" is an off pixel, "1" is an on pixel, "2" goes to the next line, and "3" means it's the end of the sprite.

DrawSpriteFast works like this:


Code:

    ld b, 10
    ld c, 10
    ld hl, sprite
   
    call DrawSpriteFast
...
sprite:
   .db %00010000
   .db %00101000
   .db %00101000
   .db %00101000
   .db %00101000
   .db %01111100
   .db %00010000
   .db %00000000


DrawSpriteFast is zero-terminated.

For the camera, I'm just adding a pretty simple routine:


Code:
ld b, 3
ld c, 7
ld a, 3
call DefineCamera


Basically, DefineCamera just takes and X, Y, and Z (bc and a) and stores it in memory for later.
When you draw a point onto the screen, the points location is adjusted based on the camera.
So, if you move the camera forwards, everything else will go backwards. If you move it left, everything else will go right.

Finally, I'm adding CheckCollision.
This will work like so:


Code:
ld b, 10
ld c, 10
ld h, 3
ld d, 6
ld e, 3
ld l, 4
call SetCube1

ld b, 11
ld c, 12
ld h, 3
ld d, 6
ld e, 3
ld l, 4
call SetCube2

call CheckCollision


"CheckCollision" will check if two objects are colliding, and set the Z flag if true, and reset it if false.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement