I have some untested code that prepares objects for drawing (find eligible candidates, sort by distance). If it works correctly, then all you need is to implement the rendering code which should be straight-forward.

Code:

    ld hl,obj_array
    call seive_sort
    call render
    ;<<code>>
    ret
seive:
;save our obj_array pointer
;start index at -1
    ld (obj_array_ptr),hl
    ld a,-1
    ld (obj_index),a
    push af
    pop af
;now we loop through the array
seive_loop:
;our obj_array (array of objects) needs to be scanned and sorted
;the first thing is to update our index
    ld hl,obj_index
    inc (hl)
    ld hl,(obj_array_ptr)
;Get the first byte of the object's code
;If it is 0xFF, then the object array is finished and we move on to sorting
    ld a,(hl)
    inc a
    jp z,sort
    inc hl
;Now we get the coordinates of the object relative to the map
    ld e,(hl)
    inc hl
    ld d,(hl)
    inc hl
    ld (obj_array_ptr),hl
;Now we need to get the coordinates relative to the player
    ld hl,(player_coords)    ;y,x
    ld a,e
    sub l
    ld e,a
    ld a,d
    sub h
    ld d,a
;Now we rotate based on the player's view angle
    call rotate_de
;If the adjusted y-coordinate is negative, this is behind the player
    ld a,e
    or a
    jp m,seive_loop
;Now we check the the x-coordinates. This is a bit complicated:
; If the x-coordinate is 0, it is directly ahead of the player, so draw it
; --Side Note--
;    The player view angle can be drawn using the graphs of y=4x, y=-4x.
;    This is almost exactly 10 binary degrees, but much easier to compute
; To check if an object is in view, if x is negative, we draw a line of slope
; -4x from the point to locate the x intercept. If this is greater than zero, it fits
; For positive x, we find the x intercept of the line of slope 4x passing through the point
; If this is negative, we are good to go!
; Doing the math, we need 4x+y<=0 for negative x, 4x-y<=0 for positive x
    ld a,d      ;x-coord, we need it multiplied by 4, so mul by 2 gives us the sign, too!
    add a,a
    jr nz,$+7
    ld d,48
    jp accept
    push af     ;save this for later
    jr nc,$+4
    neg
    add a,a
    jr c,seive_loop-1
    sub e
    neg
    jp m,seive_loop-1
;so now we know object is in range
;What we want to do know is figure out the x-coordinate to display the object
;Basically, if we take a horizontal slice of the view range that intercepts the object
;we need how far the object is from the edge divided by total width of the view range
;then we multiply by the screen width (96)
;
;We did the "push af" before to capture whether or not it was in the left of the view range
;or not. this just means we need to do 1-dist_from_edge/total_dist
;Total distance is 2*y/4 = y/2, so we need to perform 96*x/(y/2) = 96*(2x/y)
;This algorithm is hackadasical (<--- made up word), but it relies on the fact that
;2x<y<128 which is always true
;a=4x, e=y
    ld d,o \  sub e \ jr nc,$+3 \ add a,e \ rl d
    add a,a \ sub e \ jr nc,$+3 \ add a,e \ rl d
    add a,a \ sub e \ jr nc,$+3 \ add a,e \ rl d
    add a,a \ sub e \ jr nc,$+3 \ add a,e \ rl d
    add a,a \ sub e \ jr nc,$+3 \ add a,e \ rl d
    add a,a \ sub e
    ld a,d
    cpl
    ld d,a
    ccf
    rla
    add a,d
    ld d,a
    pop af
    jr nc,$+6
    ld a,96
    sub d
    ld d,a
;now we need to write our un-adjusted y, adjusted x, and obj_index to the sort buffer
accept:
    ld hl,sort_buf
    inc (hl)
    ld hl,(sort_buf_write)
    ld (hl),e
    inc hl
    ld (hl),d
    inc hl
    ld a,(obj_index)
    ld (hl),a
    jp seive_loop
sort:
;;Use merge-sort
;;data is .db y,x,index
;;sort descending by y
;;Up to 56 objects
;;
;;Outputs: A as the number of objects to draw
;;         HL points to the first object
    ld bc,$0101
sort_loop:
    ld hl,sort_buf
    ld a,(hl)
    inc hl
    cp b
    ret nc
sort_loop1:
    push bc
    sub b
    jr nc,$+8
    add a,b
    ld b,a
    xor a
    jr c,$+7
    sub c
    jr nc,$+5
    add a,c
    ld c,a
    xor a
    push af
    ld a,b
    add a,l
    ld e,a
    ld a,h
    adc a,0
    ld d,a
    call merge_sorted
    pop af
    pop bc
    or a
    jr nz,sort_loop1
    sla b
    ld c,b
    jp sort_loop   
merge_sorted:
;;Inputs:
;;    HL points to one sorted list
;;    DE points to another sorted list
;;    B is the size of the first list, non zero
;;    C is the size of the second list
;;Outputs:
;;    The list is merged and sorted, and written back
;;    HL points to the next set of sublists
    ld a,c
    or a
    ret z
    ld ix,sort_buf+1+3*56
    push bc
    push hl
merge_and_sort_loop:
    ld a,(de)
    cp (hl)
    jr c,copy_list2
    ld a,(hl)
    ld (ix),a
    inc hl
    inc ix
    ld a,(hl)
    ld (ix),a
    inc hl
    inc ix
    ld a,(hl)
    ld (ix),a
    inc hl
    inc ix
    djnz merge_and_sort_loop
;copy the rest of the second list
;actually we will just cheat and write back our current data
;No use in copying the second list just to copy back
    push ix
    pop hl
    ld de,sort_buf+1+3*56
    ld a,c
    or a
    sbc hl,de
    ld b,h
    ld c,l
    pop hl
    ex de,hl
    ldir
    ld c,a
    ex de,hl
    add hl,bc
    pop bc
    ret
copy_list2:
    ld a,(de)
    ld (ix),a
    inc de
    inc ix
    ld a,(de)
    ld (ix),a
    inc de
    inc ix
    ld a,(de)
    ld (ix),a
    inc de
    inc ix
    dec c
    jr nz,merge_and_sort_loop
;now we copy the rest of the first list
    push ix
    pop de
    ld a,b
    add a,a
    add a,b
    ld c,a
    ld b,0
    ldir
    pop de
    pop bc
    ld a,b
    add a,c
    ld c,a
    ld b,0
    add a,a
    add a,c
    ld c,a
    ld hl,sort_buf+1+3*56
    ldir
    ex de,hl
    ret
render:
;;Inputs: A is the number of objects to draw, HL points to the first object
;;Destroys: Assume all
;;Notes:
;;    Objects are stored as (y,x,index)
;;    Y needs to be adjusted for drawing
;;    X is already adjusted
;;    "index" refers to the object's index into the list of objects
;;    This needs to be used to retrieve the rest of the object information
    ret
rotate_de:
;d = x
;e = y
;-(player_angle) is the amount by which to rotate
;
    ld a,(player_angle)
    neg
;    x = x*cos - y*sin
;    y = x*sin + y*cos
;get cos(a), sin(a)
;note cos(a) = sin(a-64)
    ld c,a
    add a,a
    xor c
    ld a,c
    jp p,$+5
    neg
    and %00111111
    ld hl,sine_table
    add a,l
    ld l,a
    jr nc,$+3
    inc h
    ld a,(hl)
    bit 7,c
    jr z,$+4
    neg
    ld b,a
    ld a,c
    add a,64

    ld c,a
    add a,a
    xor c
    ld a,c
    jp p,$+5
    neg
    and %00111111
    ld hl,sine_table
    add a,l
    ld l,a
    jr nc,$+3
    inc h
    ld a,(hl)
    bit 7,c
    jr z,$+4
    neg
    ld b,a
;c is sine
;b is cosine
;d = x
;e = y
    push de
    ;x*cos - y*sin
    ;d*b - e*c
    ;x*sin + y*cos
    ;d*c + e*b

    ld a,b
    ld e,d
    call A_Times_E_signed
    pop de
    push de
    push hl
    ld a,c
    call A_Times_E_signed
    pop de
    or a
    sbc hl,de
    ex (sp),hl
    push hl
    ld a,h
    ld e,c
    call A_Times_E_signed
    pop de
    ld a,b
    ld b,h
    ld c,l
    call A_Times_E_signed
    add hl,bc
    pop de
    ld a,e
    add a,a
    ld a,d
    adc a,0
    ld d,a
    ld a,l
    add a,a
    ld a,h
    adc a,0
    ld e,a
    ret


A_Times_E_signed:
;;Inputs: A,E
;;Outputs: HL
;;250+6b+34a
;;worst: 332cc
    ld a,e
    add a,a
    sbc a,a
    ld d,a
    ld a,l
    ld hl,0
    rlca \ jr nc,$+5 \ ld l,e \ ld h,d
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add hl,hl \ rlca  \ jr nc,$+3 \ add hl,de
    add a,a
    ret nc
    ld d,e
    ld e,0
    or a
    sbc hl,de
    ret


Also, I am assuming you already have a sine table of the first 64 elements Razz
The last 5 errors stopping compile of Slender:


Code:
Warning: Instruction ld b,* does not expect an index - check parentheses. [slender_movement.asm:22]
Warning: Instruction ld b,* does not expect an index - check parentheses. [slender_movement.asm:36]
Warning: Instruction ld b,* does not expect an index - check parentheses. [slender_movement.asm:54]
Warning: Instruction ld b,* does not expect an index - check parentheses. [slender_movement.asm:62]
Error: Could not parse expression 'backgroundSelect' (Invalid number). [main_loop.asm:7]


As for the first four, I'm hoping i can still use ld b,(**). If not, i'll have to work around that.

As for the last one, that's a routine I have yet to write, so yeah. That will set the background for the game (so that I can make it alterable since "The Arrival" occurs during the day too).
There's no ld b,(addr) command. You can do ld bc,(addr-1) if you want (puts (addr-1) into c, (addr) into b). Otherwise, you generally do ld a,(addr) \ ld b,a. Not that ld bc/de/sp,(addr) are prefixed instructions and thus take an extra byte (4 bytes total) and 4 cycles (20 total). ld hl,(addr) is not prefixed so it's slightly faster and smaller, though i think you can use the same prefix as with bc/de ($ED) and it'll still work the same. Don't know why you'd wanna do that, though.
Update: First official compile of Slender this morning. It crashed immediately. So, time to debug :p

Also, anyone with Git access to my Slender repo can download the beta from the path "/home/git/projects/slender/MONTH/DAY/slender.8xp". If anyone else wants to test.
Update: we now see a splash screen, then a crash. Screenshot posted on project page, under Gallery/Screenshots.


Screenshot of title screen.

Progress Update:

Project page. After Deep pointed me to the jQuery.mobile plugin, was able to use the "tap" method to integrate with my onclick triggers. The project page for Slender is now mobile-capable.

Slender. After being poked by Xeda on the fact that her text routine crashes if text goes off screen, I revised my calls to the routine such that text wraps manually. Crash persists.
The older screenshots were irking me bc the text wasn't entirely readable so I made a simpler, cleaned up version of it. And yes, that's a high-res, scaled down Slender font.

Update

New font to the project page. http://clrhome.org/slender. Also changed logo from Slender, to Slender-TI to distinguish it from the original, both so my project has a distinct name and to avoid copyright issues.

A few changes to the source code to try to find this bug and still it persists. It crashes immediately after the splash screen (pressing 2nd). I'm toying with the idea that it may be the keypress itself that is crashing it (somehow the value of a is getting distorted during the keypresses, but i added some push/pop af and it persists. My second thought is that its somewhere in my object rendering loop, and since I'm still pending a sorting algorithm, it seems pointless to debug that at this point.
Update

Finally resolved the Slender crash. Turns out if I'm activating a second keygroup, I need to reset the driver. Well, lesson learned. Currently waiting on a sorting revision to my rendering code and 2 & 1/2 sprites. Then, we can have a release.
Update

A bit of restructuring of the slender repository. Files renamed, consolidated, folders renamed to more explanative things. Main game loop moved into main file. Support for multiple keypresses at once added. This allows you to do things like walk and collect a page, or turn while walking, but it also allows you to do dumb things like turn both ways, and walk back and forth at the same time. Also streamlined and fixed the filtering of objects into a stack of objects on screen, so still have the by-distance sorter to do. Still have 2 sprites left to do. User's Guide is in progress.

Also, I asked this in another topic, but I'll post it here since it technically belongs here. There is a header somewhere for a shell that supports no-stub. I thought it was Mirage, but was told that it was Ion. Is there documentation for this? And if the header is, for example, an Ion header, will it work for DCS, and will it also work if no shell at all is present?
ACagliano wrote:
Also, I asked this in another topic, but I'll post it here since it technically belongs here. There is a header somewhere for a shell that supports no-stub. I thought it was Mirage, but was told that it was Ion. Is there documentation for this? And if the header is, for example, an Ion header, will it work for DCS, and will it also work if no shell at all is present?

There might be other documentation for this that's better, but some info about the Ion header is available here: http://www.joewing.net/projects/ti83/ion/devel.shtml

By choosing between ret and xor a at the beginning of your program, you can choose if it will work when it's run without a shell. DCS supports both of these types of Ion headers and will display the description when one is present.
Yeah, you just need to change the ret to xor a. You don't even need to put a description, a .db 0 would probably be enough for shells like Mirage and DoorsCS to handle it. It will work with any recent shell or without a shell, as long as you don't use any ion libraries. Also, keep in mind that nostub programs are much more limited than non-shell programs because the OS limits them to 8kb. It'll refuse to run the program if it's too large, so you'll need to run it with a shell or write a launcher that copies itself to saferam and then copies your program to 9D95 and deletes it afterwards. You'd have to handle program writeback yourself, though.
Program size is not a problem. The game seems like it will clock in around 6-7k. And is that executable size limit whole-program or executable-part only?

Also, I use no libraries. It is a stand-alone program. Just wanted shell support, should one choose to be used. So I'm assuming DCS/Ion/MOS will interpret this properly:


Code:

.nolist
#include "ti83plus.inc"
#include "dcs7.inc"      ; just bc i use some RAM equates from it
.list
#include "includes/defines.inc"

.variablename "SLEND8P"
.org progstart
.db $BB,$6D

Init:
   xor a
   jr nc,Start
Description:
       .db "Slender: Eight Pages",0
Start:
   \\ program here

.end
.end


Also, I now have, but will not reveal yet, a storyline for a 4-title original Slender series. Smile
That should work fine, yeah. And it's a total program size limit when run from the TI-OS, not an executable code limit.
With the return to progress on this game comes another redesign of the project page at http://clrhome.org/slender. Also comes substantial progress-- completed saving/loading, keypress detection, movement, looking, death conditions, assorted math routines, a raycaster and frame rendering (by Zeda). All that is left is one part of the frame rendering, sprites, and the map, and then we are finished.

ps: no screenshots yet bc i made the incredible choice of doing the rendering last :p
Without rendering things to the screen how do you know things are working correctly? Question
chickendude wrote:
Without rendering things to the screen how do you know things are working correctly? Question

Rendering simply projects data that is already there and monitorable. I step the code one line at a time, watch how it flows, and watch the registers/RAM state. Seems to do what it's supposed to.
While I've been working on Star Trek MP for the CE, I decided to give my Slender CE project a bit of a nudge in the "complete" direction, by tossing in a ported version of Star Trek's rendering engine and modifying the mapdata structures a bit. I was inspired to do this bc of the upcoming release of an official Slenderman movie.

I built and created a working program, but the renderer is a little... off. Firstly, you seem to only see one tree, nothing else. Looking around (left/right) works properly but moving forward or backward does not. Regardless of what direction you're moving in you seem to move away and then towards. I wonder if this is an issue with my rendering algorithm or my map generation algorithm, or possibly because you're overflowing the range quickly.

Here's a link to the source, for anyone wishing to review: https://bitbucket.org/anthonycagliano/ti-slender-ce/.

Teaser:
Any updates, or is this just another forgotten game? Sad
Legoman314 wrote:
Any updates, or is this just another forgotten game? Sad

This game is still in progress, but I'm having a weird and frustrating issue. The rendering engine seems to render only the Slender sprite and one of the other sprites. I'm wondering if this is actually an issue with the spawning algorithm instead. I've tried re-writing, checking data types etc, but cant figure this out.

Moving causes even more weirdness. I've enclosed a screenshot and a link to the source:
Source: https://bitbucket.org/anthonycagliano/ti-slender-ce/
  
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 2 of 3
» 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