Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - jaymzjulian

#1
Code Swap / Lit/Culled 3d objects
August 06, 2020, 11:25:11 AM
So I was playingh aroundw ith ways to reduce my draw load, and I kind of fell back to some experiements I did a while ago about culling - the problem at the time being, gsbasic isn't fast enough to really do what I needed without me running out of cycles.

But then I had the idea to use kmeans clustering to quantize the normals to a smaller number - 6, in the case of the demo presented here - and do the culling and lighting on larger sets of polys instead.  Shockingly, this actually works out.  So the procedure ends up being:

a) Generate a set of lines and normals via "some mechanism" (I have a couple of mechanisms for this, one of which involves blender, and one of which involves generating the normals from the lines assuming the objects are vaugely built arounda center)
b) Reduce these set of normals to clusters - I'm using python's sklearn.cluster.KMeans for that!
c) in gsbasic, use vectorrotate and friends to transform the normal set - of course, you need to do the world translate/rotate as well - i.e. consider the camera!  But that's well within the realms of achievable now....

So you end up with an array of objects which happen to mesh together.  There is a couple of serious downsides this this technique, mind you:

a) because the objects aren't linked anymore, there is extra ReturnToOrigin() calls!  indeed, drawing this tree returns to origin 6 times..... we can't easily avoid this, because even if we did relative pen movement things, we don't know if part of the obhect will be drawn until the math is done!
b) things do look better if your object is made of polys rather than lines at the outset, however then you have double-draw issues.  Blender is actually really good at creating normals that don't suffer this, mind you.... essentially if you have "smooth" point normals (as are genearted by the smooth object modifier), it works out well, whereas if you have "flat" surface normals, it doens't work out so well unless you double draw edges, defeating the point of what we're trying to do here.  Of course, there is no reason NOT to smooth your normals when the object isn't filled, so..... it actually doens't matter as much as you'd think... (after all, there is no fill, hence no gouroud shading/phong shading to deal with!)


So you end up with the attached demo.  I did also attach the python I use to generate that set - it's inputs are kind of very specific, though, it's absolutely not yet a generic tool, but i figured the technique was at least worth sharing!
#2
Code Swap / Cubic interpolation
July 09, 2020, 04:39:55 PM
Everyone needs to interpolate, right?  I use this for pathing:


function cubic_interpolate(a,b,c,d,t)
  ia = -a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0
  ib = a - (5.0*b) / 2.0 + 2.0*c - d / 2.0
  ic = -a / 2.0 + c / 2.0
  id = b
  return ia*t*t*t + ib*t*t + ic*t + id
endfunction


or a faster version:

function fast_cubic(a,b,c,d,t)
  return (-a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0)*t*t*t + (a - (5.0*b) / 2.0 + 2.0*c - d / 2.0)*t*t + (-a / 2.0 + c / 2.0)*t + b
endfunction


fast point in a 2d dot array via inlining:
(doing 512 of these takes 360 ticks, vs 628 ticks if you call functions instead!)

      a = land[((sy-1) & (dot_horizon-1))+1, ((sx-1) & (dot_horizon-1))+1]
      b = land[((sy) & (dot_horizon-1))+1, ((sx-1) & (dot_horizon-1))+1]
      c = land[((sy+1) & (dot_horizon-1))+1, ((sx-1) & (dot_horizon-1))+1]
      d = land[((sy+2) & (dot_horizon-1))+1, ((sx-1) & (dot_horizon-1))+1]
      ya = (-a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0)*yoffset*yoffset*yoffset + (a - (5.0*b) / 2.0 + 2.0*c - d / 2.0)*yoffset*yoffset + (-a / 2.0 + c / 2.0)*yoffset + b

      a = land[((sy-1) & (dot_horizon-1))+1, ((sx) & (dot_horizon-1))+1]
      b = land[((sy) & (dot_horizon-1))+1, ((sx) & (dot_horizon-1))+1]
      c = land[((sy+1) & (dot_horizon-1))+1, ((sx) & (dot_horizon-1))+1]
      d = land[((sy+2) & (dot_horizon-1))+1, ((sx) & (dot_horizon-1))+1]
      yb = (-a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0)*yoffset*yoffset*yoffset + (a - (5.0*b) / 2.0 + 2.0*c - d / 2.0)*yoffset*yoffset + (-a / 2.0 + c / 2.0)*yoffset + b

      a = land[((sy-1) & (dot_horizon-1))+1, ((sx+1) & (dot_horizon-1))+1]
      b = land[((sy) & (dot_horizon-1))+1, ((sx+1) & (dot_horizon-1))+1]
      c = land[((sy+1) & (dot_horizon-1))+1, ((sx+1) & (dot_horizon-1))+1]
      d = land[((sy+2) & (dot_horizon-1))+1, ((sx+1) & (dot_horizon-1))+1]
      yc = (-a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0)*yoffset*yoffset*yoffset + (a - (5.0*b) / 2.0 + 2.0*c - d / 2.0)*yoffset*yoffset + (-a / 2.0 + c / 2.0)*yoffset + b

      a = land[((sy-1) & (dot_horizon-1))+1, ((sx+2) & (dot_horizon-1))+1]
      b = land[((sy) & (dot_horizon-1))+1, ((sx+2) & (dot_horizon-1))+1]
      c = land[((sy+1) & (dot_horizon-1))+1, ((sx+2) & (dot_horizon-1))+1]
      d = land[((sy+2) & (dot_horizon-1))+1, ((sx+2) & (dot_horizon-1))+1]
      yd = (-a / 2.0 + (3.0*b) / 2.0 - (3.0*c) / 2.0 + d / 2.0)*yoffset*yoffset*yoffset + (a - (5.0*b) / 2.0 + 2.0*c - d / 2.0)*yoffset*yoffset + (-a / 2.0 + c / 2.0)*yoffset + b

      return (-ya / 2.0 + (3.0*yb) / 2.0 - (3.0*yc) / 2.0 + yd / 2.0)*xoffset*xoffset*xoffset + (ya - (5.0*yb) / 2.0 + 2.0*yc - yd / 2.0)*xoffset*xoffset + (-ya / 2.0 + yc / 2.0)*xoffset + yb
#3
So I've decided to write something _small_, that i can knock out in a week or three, as a palette cleanser before trying to finish one of my other bigger games.  Which one should I do?

reference:
https://www.youtube.com/watch?v=dedw3Ji-6kE <-- this is crazy comets
https://www.youtube.com/watch?v=9Lodc0kFYuo <-- this is wizard of wor
#4
Game Swap / VxTron32 release 1.0
June 17, 2020, 07:59:15 PM
So one near complete rewrite later, here's VxTron32 - as 3d tron game for the vectrex 32.  For the most part, it contains what it says on the tin - it's the tron light cycles game, for one or two players.  It also contains ducks.

https://www.youtube.com/watch?v=K1_07VBNwOY
another: https://www.youtube.com/watch?v=T2bl8Syi6VA

Controls for one player (third person):

joystick - move camera
button 1 - turn left
button 2 - turn right
button 3 - zoom camera in
button 4 - zoom camera out

Controls for one player (first person):

button 1 - turn left
button 2 - turn right
button 3 - peek left
button 4 - peek right

Controls for two players on one controller:

button 1 - turn left
button 2 - turn right
button 3 - turn left (player 2)
button 4 - turn right (player 2)

Un-combined source is at https://github.com/jaymzjulian/vltron

ProTip: Generally I watch the map more than the 3d display when trying to judge distance, because there is still an amount of vector drift.  You can totally play it in pure 3d, and sometimes I do, but it helped me, at least!  That applies less in first person mode....

There is theoretical support for two players on two controllers, however since I don't own two controllers, who knows if it works.  I'll put out a patch release if it does not....

Note: You need to copy all of the files in the zip to your vectrex32 for this to run (except the README.md, it doesn't read that ;)) since, in order to conserve memory, certain items are streamed from the storage.

(My next game will definitely not take six months ;))
#5
So I keep running out of memory (this is what i get for starting to have animations, right ;)), which kind of sucks, but then it occurred to me that having a second copy of the data for my sprites in memory was kind of a problem..... and indeed, this got me back to being able to boot into the game, so I though i'd share it:


function reado32(filename)
  file = fopen(filename, "rt")
  dimensions = Int(Val(fgets(file)))
  command_count = Int(Val(fgets(file)))
  print "Reading "+command_count+"commands of "+dimensions+"d object from "+filename
  dim o[command_count, dimensions + 1]
  for j = 1 to command_count
    o[j, 1] = Int(Val(fgets(file)))
    for k = 1 to dimensions
      o[j, k+1] = Val(fgets(file))
    next
  next
  print "done!"
  return o
endfunction



The format is:
[dimensions]
[commands]
... and then [commands] list of comamnds.  I formed my test file by taking a function, and doing:

cat lightcycle.bai | sed 's/MoveTo/0/g' | sed 's/DrawTo/1/g' | sed 's/,/\r/g' | sed 's/\{/\r/g' | sed 's/}/\r/g' | sed 's/_/\r/g' | sed '/^ *$/d' > lightcycle.o32
and then filling in my dimensions(3) and vertex count (145) at the top of the file, resulting in:


3
145
0
-0.284963
-0.242065
1.085209
1
-0.284963
-0.550938
1.394082
1
-0.452639
-0.242065
1.394082
1
-0.284963
-0.242065
1.702956
#6
Code Swap / Object Explosion Generator
April 03, 2020, 12:10:59 PM
We all need to blow things up in our games, right?  This library will do that to any any object for you - i'm using the rose object i play with as a demo for this, but any LinesSprite or Lines3dSprite format object should do!  Assuming your line count is "normal", it's entirely reasonable to do this in realtime during your game - indeed, that's what the sample shows - although you could use it to generate an animation instead, with a little modification.

demos:

these are all deliberatly slow so you can see things :).

explosion-demo-nobreak - explode a simple object, dont disconnect the lines
explosion-demo-break - explode a simple object, disconnect the lines
explosion-demo - explode a complex object.  Note that, for some reason, this will sometimes crash the vectrex32 hard right now :(.  I don't know why!  Whjich is a shame, since it looks cool!

How to use in your own stuff:

1) include explosion.bai
2) call the function "prepare_explosion" with the following params:

' Params:
' dimensions - 2 or 3
' obj - the LinesSprite format object
' world_scale - scale of the world
' point - where to explode
' x_impulse - base impulse to hit object with on the x axis
' y_impulse - base impulse to hit object with on the y axis
' x_random - additional random impulse for x
' y_random - additional random impulse for y
' break_apart - true/false - do we break the vectors?


3) call either explode2d or explode3d each frame until you're done with the explosion.

sample:


' get the object
rose_object = rose()

' prepare the object for exploding - just expanding variables here for clarity :)
world_scale = 40
x_impulse = 2.5
y_impulse = 5.0
x_random = 2.5
y_random = 5.0
rose_explosion = prepare_explosion(2, rose_object, world_scale, {0,-400}, {x_impulse, y_impulse}, {x_random, y_random}, 9.8, -400, false)

' put it on the screen
LinesSprite(rose_explosion.dest)
controls = WaitForFrame(JoystickNone, Controller1, JoystickNone)
while controls[1,3] = 0
  call explode2d(rose_explosion)
  ' wait for next frame :)
  controls = WaitForFrame(JoystickNone, Controller1, JoystickNone)
endwhile
#7
General Discussion / Guidence on code memory usage
March 10, 2020, 01:44:53 AM
EDIT: safely ignore this one if you like, since I managed to make my optimizer way better and get it down to about 2000 lines, which is fine :)

So, let me preface this with that I'm trying to do something stupid - specifically, i wrote a static recompiler from 6502 to gsbasic, because I wanted to convert some arcade games, and this seemed like a sensible approach (if you've seen the stuff at https://norbertkehrer.github.io/ast_js.html , basically the same sort of thing, but applied to gsbasic).

So this actually works on a bunch of test cases, but if I try and do all of asteroids, well, of course the vectrex32 throws an out of memory and reboots - which kind of makes sense, since it's 7395 lines of basic code.   But I'm still somewhat thinking I can optimize my way out of this, which leads me to my question:

When loading basic code, _what_ takes ram vs what doesn't.  What I mean by that:
* if i make my variable names smaller, does that save ram, or are they tokenized out?
* if i use a hex representation of numbers, does that help, since they are smaller, or are they tokenized out?
* are comments removed entirely, or do they count for the purposes of this?
* does one big function, vs a bunch of little functions, make a difference as far as you know?

I did some testing, and I can definetly load about 50% of the size, so hopefully some optimization will help me.... but i was kind of thinking in terms of where to focus that, if there was some "big win" that isn't obvious from the outside :)
#8
Just a simple release bundler - since it's easier to distribute one file than lots of files....  this is in my vx32tools repo at https://github.com/jaymzjulian/vectrex32_tools with the rest of my work tools.

I might have this later bundle binary files too - though currently I haven't worked out a good way to encode them without taking up all the ram/disk, so it might not happen!  But I'm less concerned with those - a .bas + a .ayc isn't too bad, whereas my current situation of like 8 files iwht generic names is not nearly as great ;).


import sys,shlex

def parsefile(f, outf):
  j=open(f).readlines()
  for line in j:
    if line.strip().startswith('include'):
      parsefile(shlex.split(line)[1], outf)
    else:
      outf.write(line)

if len(sys.argv)<2:
  print("Usage: vx32-bundle.py infile.bas outfile.bas")
outf=open(sys.argv[2], "wt")
parsefile(sys.argv[1], outf)
#9
Essentially, an advanced flag to NOT call wait_recal if, for some reason, I know better - the use case I'm doing is, for example, on the vxtron32 title screen I'm manually balancing two different dpram pages - one of which is very fast to execute (indeed, does no line drawing) but was causing a ram overrun. 

Currently I solve this by setting the framerate really high - but you actually can't go higher than 150fps, afaict (at least, when i set framerate to, say, 400, and request it back, that's what I get), and really in those cases i'd rather it not be called at all - i.e. i want to always call it on my first WaitForFrame call, but not necessarily again if i'm calling it a second time to deal with an error state or such like.

If only rom wasn't rom, i'd just nuke it myself with a codesprite ;)
#10
Game Swap / vxtron32 beta 1
January 18, 2020, 02:20:42 PM
Since I've been pottering around on this for about 2 months now, on and off, and we've been having some fun playing it here, I decided to make a beta release of vxtron32 - especially since I suspect won't have much vectrex time for a few weeks.   Note that you MUST copy both the .bas and the .ayc to your vectrex32, or the game won't run.

But there will be a later release which fixes at least the stuff below....

Bugs/Todos:
There is some pretty bad code in there still - in particular, i do want to rework how collisions and bike movement is done (that is to say, I want to allow fractional movement by not using a grid, but rather line intersection, for collisions), which I was going to do before this, but that doens't really affect the gameplay (other than unlocking the internal logic from being 20fps, BUT most of the time you're not going above that anyhow ;)).  I do want to fix this, but I wanted to get some outside feedback and so I'm not delaying for that right now.

One of the biggest "TODOs" is that the music is NOT final - it's actually currently from the atari st game "Switchblade".  I am working on an original soundtrack for this, but learning the AY took a little longer than I expected, and I didn't want to hold up other people playing it for that :).

I've seen the thing just crash a few times, but not reliably.  If it does for you, something has gone wrong that I'll need to address - there is a variable at the top, "release_mode" that switches that to tell you _why_ it did that, hopefully.

Also, yes, i'm aware the AI isn't great :).

Credits/Thanks:

Thanks to Ilkke for the cycle models used in the game, as well as to Bob for his massive help with me getting to grips with the platform. 

Controls:
As per the readme:

Controls for one player (third person):
joystick - move camera
button 1 - turn left
button 2 - turn right
button 3 - zoom camera in
button 4 - zoom camera out

Controls for one player (first person):

button 1 - turn left
button 2 - turn right
button 3 - peek left
button 4 - peek right

Controls for two players on one controller:

button 1 - turn left
button 2 - turn right
button 3 - turn left (player 2)
button 4 - turn right (player 2)

Hopefully someone other than me enjoys this ;)

EDIT: video - https://www.youtube.com/watch?v=-MObh_HrQ2w

EDIT2: see later post for zip file now :)
#11
This is a weird request, but I actually trip over this a lot.  What I was thinking about is an operator that is mod, but instead of being based at 0, it's based at 1.  This is beacuse, of course, gsbasic arrays start at 1 - so to cycle one, you either have to:

a) have your internal pointer based at 0, and have every access be +1, and remember that, or
b) have code that looks like:

if menu_cursor > Ubound(menu_data)
  menu_cursor = 1
endif

rather than the usual

menu_cursor = (menu_cursor + 1) mod Ubound(menu_data)


I've no idea what one would call such an operator, mind you....
#12
Code Swap / DPRam multiplexing in 1.21
December 31, 2019, 12:24:46 PM
EDIT: From 1.22 onwards, this is redundant, and you absolutely shouldn't use it - it's left here entirely for historical value :)


I threw this together to test some things - it is a generic dpram multiplexor.  It's the simplest possible implementation, and with that comes a couple of caveats, the biggest one being that it _demands_ the pattern of:

ReturnToOrigin()
Object()
ReturnToOrigin()
AnotherObject()

because it simply slices at an arbitrary place where the drawing is completed.  For my actual games, I have a bit more intelligence than this, in that I actually track which object is a ReturnToOrigin sprite, and always clip there - but my method for doing that currently involves setting up magic arrays for that.  Bob did add tagging in the most recent release, and maybe I'll do a generic example at some point to demo that.

This is not without it's drawbacks, though, and this demo adequately demostrates them - which is that, of course, the more vectors you fill your screen with, the more it will flicker.  I picked a really bad case scenario on purpose here, to try and flesh out some issues, but if you change the scale from 48 to 16 in the basic file, you can see that at that size it's really stable - it's all about the long lines :).  Which is sort of the point - I ended up with a game that acutally did run between 20 and 30fps, which is enough, but really needed two dpram pages to do so!

As an aside: I did benchmark using an array of objects instead of calling DrawingListSprite, and it _is_ slightly faster, though we're talking around the 5% mark, so it's probably not worth it unless you have a reason (like better slicing!), but again, this is a starting point, not an ending point, hence being in code swap and not game swap :).


EDIT: I attached the wrng file :)
#13
General Discussion / Lightpen Game Concepts
December 31, 2019, 12:07:20 PM
I'm not going to do any of these any time soon, but in case anyone else was interested, I had some ideas that would be well doable with the CodeSprite stuff that Malban came up with:

a) a drag-and-drop puzzle game like E-Motion ( https://en.wikipedia.org/wiki/E-Motion ).  That game is based around colour, so you'd need to change it to shaps, but ti could be a good fit.  Give each "object" and ID, and then drag them around based on which part of the object is touched.... in my head I think i'd implement it by splitting each one into a couple of "virtual" sprites, and float them towards the center? (in the original you nudge them with a ship, but "drag with the lightpen" is totally a mechanic that would work well...)

b) Since people are hooking up lightgfuns to the port - the nice thing about this is that it _only_ requires contact and a trigger button - you could do something like Operation Wolf pretty easily.

c) The incredible vectrex machine - this one would be a lot of work, since you'd have to impelemnt a full drag/drop system, plus physics.  But the physics are absolujtely doable on the v32, so maybe?

d) lemmings!  I _suspect_ you might have some flicker troubles at 50 lemmings, though, and I've no idea how you'd do the environments, but it'd be cool if it could be made to work!  You'd have to make some modifications to the game to "vector" well, though....
#14
Right now, the "length" of a linesprite object is always the length of the object - this is _usually_ what you want, unless you want to grow/morph/otherwise manipulate it to a different number of lines, when it isn't.  Today, I'm just working around this by re-generating the entire display whenever I need to change the size of the trail sprites, however this can take a non-trivial amount of cycles when things get busy (around 20 ticks or so).  This actually isn't a problem really most of the time, but it's.... definitely clumsy.

So I could optimize that, of course - I know there is a few dumb things I'm doing in there - but my initial instinct was "well, just don't do that" and just grow the array - it's live data, after all, but that's where I hit the snag - if I define it at "max size", the object has values like:

MoveTo, 0, 0, 0
DrawTo, 1, 1, 1
Undefined
Undefined

So of course, if you try and draw this, it errors - as it should - since Undefined is, well, undefined.  So far, so copasetic.  I was actually able to work around this by doing:

MoveTo, 0, 0, 0
DrawTo, 1, 1, 1
MoveTo, 0,0,0
MoveTo, 0,0,0
MoveTo, 0,0,0

Where most of those MoveTo's are optimized out, so everything is "fine".  Works out reasonably, crisis averted, but is pretty clumsy.   As an aside, of course I could use the RemoveSprite/PutSpriteBefore function as well with a deepcopy of the array, which I actually find clumsier, myself, but it'd be doable.  But what I really want to do, is something like:

MoveTo, 0,0,0
DrawTo 1,1,1
EndDraw
Undefined
Undefined

Then when I grow the object, I can update it to be:

MoveTo 0,0,0
DrawTo 1,1,1
DrawTo 2,2,2
EndDraw
Undefined

Without having to recreate the sprite object.   My running theory is that it should be pretty easy for that code to just go "ohhey, this is the end of the object, get out!".  As always, it's entirely possible/probably I'm wrong about the internals :).
#15
Code Swap / SVG Import tool
December 22, 2019, 04:03:10 AM
I was actually inspired by the beizer curve examples, interestingly ;).

It's still imperfect, but it's working _enough_ for me to import various things from inkscape - this was important for me so that I can have one of my artist friends draw me a title screen and some sprites :).  A few notes:

* Some things are actually filled outlines - we, of course, do not handle these usefully ;).  The rose example is actually one of these, but I picked it precisely because it is hard (also because I love b&tb....)

* It can output either a function that generates a display list (for things like title screens and such) or a arrray of commands (for movable sprites and such) - see the rose and spiral examples for details of this

* There are a bunch of object types currently unimplemented, msotly because of what inkscape outputs - specifically, I haven't done arcs yet.  They "generally will work" once I find an SVG that has them though - the library i'm using supports them, i just haven't hooked it up.

* It can optimize for either a certain amount of error (say, no more than 0.1 "units"), or a certain amount of vectors (i.e. no more than 512 vectors - which is, btw, approximatly what ends up fitting in DP ram, at least 768 fails for me)

* If you're importing complex objects, which have a lot of pen drift, the static function variant supports calling ReturnToOrigin every N commands.  Without this, the rose example looks absolutely terrible and jumps all over the place, though the spiral is weirdly fine.  The _OTHER_ reason for this, is because it supports the paged-DPram mode that takes advantage of 1.21 features, which of course does not actually exist yet ;) - I tested this with a version of rose with double the vectors, and it makes it look way better :).  But I've left that out of the samples until 1.21 is released, at which point I'll update it.

* I need to improve the MoveTo optimization just a little more - it tries to pick "near origin" as the first thing, but really it should pick "Thing that causes the least MoveTo commands".  I'll probably update that in github soon.

* There should be some kind of optimization that goes "These two lines can actually combine into one line with N loss", rather than "Line X is too short" - you can see this on the straight lines of the rose sample wasting some lines where because all of the inputs are beizer curves for that svg, it will just do, you know, a bunch of segments that are identically angled.  this... should be doable.  Something like "min angle" to go with "max length" - it's totally doable, but the optimization problem is sort of interesting and i decided not to yet...

Link:  https://github.com/jaymzjulian/vectrex32_tools
Samples: attachments :)

#16
Code Swap / Bezier Curves
December 11, 2019, 11:46:42 PM
This one isn't mine, but I thought it was a cool bit of code:
https://jameltayeb.com/2019/10/29/bezier-curves-for-vectrex/ (stolen from the vectrex group on facebock)
#17
This one should be fairly simple, i think, but hey, i might be a crackmonkey :). In one of my experiments, I'm making a field of trees on a 3d plane (trying to create a jungle effect, essentially), and I want the trees to be scaled 2d sprites rather than 3d objects (think like the trees in mario64 ;)).  (in the game, things are going to hide behind the trees - ).  Of course if I _just_ want the trees, this is pretty simple - i just project myself and z-clip, and life is good, but of course I don't want something that simple :).

My current attempt at this this involves defining my tree as a Sprite3d, and then rotating the object so that it always points at the camera, which actually does work, but is super annoying, of course, and I've never gotten _quite_ right (it looks _great_ as long as I don't try and have a free camera!).  So what I really want in my life, is something that looks like:


' have a normal-ish 2d sprite - but maybe a differnet type for the system if that helps it
my_2d_sprite = LineSprite25d({ ... 2d object ... })
' place that sprite in _3d_ space, which will draw it at that location zoomed by
' whatever the projection would have x/z*d be
SpriteTransform(my_2d_sprite, { 3d_coord} )


and then have it drawn as a scaled 2d object, where the scale is appropriate for the place it is in 3d space. 
#18
So I've been creating a bunch of libraries for my dev, which is nice and all, but currently I'm putting that together with scripts and/or editor tricks - I was wondering if there is a way to load more basic files from the flash in a sort of '#include'-ish way - so not like chain behaves, and as far as I can tell now how load behaves either? 

I was thinking of using cpp for this on the PC, but obviously editing in that workflow is terrible, so i wondered if maybe you already thought of this and it's just hidden in the depths of the manual that i could not find, otherwise it's a feature request :)
#19
This is mostly getting an idea out of my head - should not even consider this one ;).  In particular, I suspect it'd be a pretty big re-architect for something that almost no-one would use, BUT maybe it can lead somewhere....

in the context of thinking about music/sound effects, I was thinking about what you'd need to do to support a sampled audio stream - stuff like mixing a couple of sample channels on the v32 side (maybe from a mod file or similar), outputting that to the AY. 

I came up with that for an 18khz output, which would be quite acceptable through the vectrex's tiny speaker anyhow, you need to transfer 600 bytes/30th.  You could reduce this to 300bytes/30th if you used 4bit samples, which i believe is what you can get without _hacks_ anyhow on the AY (i.e. stop the oscillator, waggle the volume register).  This seems.... doable - obviously, that's a fair chunk of the dual port ram (this would NOT fly with vltron ;)).  Of course, the hard part then would be timing the 6809 side.  I suspect you end up with a loop that looks like:

* start an 18khz timer
* look at timer - am i due more samples than I have played?  yes?  play next due sample from buffer
* is there more things to draw?  yes?  perform next dreawing op
* loop

This is also probably why the samples in spike sound so bad - you're going to keep losing bits while a lot of drawing is happening... essentially here you have to output a sample every 90 cycles or so.  If a line takes more than 90 cycles to draw, then there's going to be distortion.  You could, of course, reduce that rate further, making this more realistic - I know when reading up on vectrex samples, malban mentioned 8khz, which seems super low to me, but then in c64 land we do 7khz a lot, so what would i know? :).  But that would give you 185 cycles per sample, which seems even more doable - as long as you check between each line draw if you're due one yet, I think it might _actually_ work out.  Interestingly, I _suspect_ the fastest way would be acutally just write the sample to the PSG volume register unconditionally - there's no harm in it, and the check is probably longer than the read timer/update

EDIT: that last statement is a lie thanks to the way the AY is hooked to the vectrex  ;)  I forgot that hot mess!
#20
Logical operators are true/false only, but it'd be nice to do something like:

' between 0 and 7
a = a & 7
' set bit 4
a = a | 4

when doing things like dealing wth the AY particularly, of course :).  Maybe use the C-style operators of &/|/^, since the letter ones already have clear meaning that should not be changed under people :)