Skip to main content

News

Topic: Surface Questions (Read 5846 times) previous topic - next topic

0 Members and 2 Guests are viewing this topic.
  • scojin
  • [*]
Surface Questions
Okay, so I'm making a quest-log type menu that is semi-dynamic, meaning they have a set order and are organized by location, but don't appear until activated.
Like so:
Store
A
B
C
House
A
B
C
D
Forest
A
C
D

So basically I have a function that checks, orders, and creates the selections for the menu and then returns the selection order and the selection display in an object. The display is created basically like so:
Code: [Select]

object.image = new Surface(w,h);
//draw header
prim.blit(object.image,x,y,header);
//draw quests
font.drawText(object.image,x,y,whateverquest.title); //draw title
prim.blit(object.image,x,y,whateverquest.status);         //draw icon

//--------------------------------------------

object.selection = selection_array;
object.display = object.image.toImage();

return object


The problem is when I call the menu to be displayed, it only displays the title(from drawText) and not the header or icon(from prim.blit). This is my first go with surfaces, so maybe I'm just not using them right, or maybe I'm missing something?
Thanks in advance.
  • Last Edit: March 05, 2017, 11:40:12 am by scojin

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #1
Code: (javascript) [Select]

prim.blit(obj.image,x,y,header);


Shouldn't that be object.image?
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • scojin
  • [*]
Re: Surface Questions
Reply #2
Yep, that was just a typo. Fix'd
My actual code has a bit more to it, so I made a brief example. :P

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Surface Questions
Reply #3
To draw on surfaces you need to use the surface API:

Code: (javascript) [Select]

object.image.drawText(x, y, text);
object.image.drawImage(x, y, image); // not too sure on this one


But what are you trying to do? Is this for a menu or for an on-screen hud? I've never used surfaces to draw many things on to unless I'm pre-processing images into one image to draw, but rarely do I do that.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #4

Code: (javascript) [Select]

object.image.drawText(x, y, text);
object.image.drawImage(x, y, image); // not too sure on this one


But what are you trying to do? Is this for a menu or for an on-screen hud? I've never used surfaces to draw many things on to unless I'm pre-processing images into one image to draw, but rarely do I do that.


He's using the Sphere v2 API (note the new Surface(...)).  Surfaces have no built-in primitives in Sphere v2, you're meant to use Galileo (i.e. Shape objects).  See:
https://github.com/fatcerberus/minisphere/blob/v4.5.4/docs/sphere2-api.txt#L913-L938

The prim module included with the engine provides equivalents for most of the classic primitives, but even it uses Galileo under the hood to the actual rendering.  Here's the code if you're curious how that works:
https://github.com/fatcerberus/minisphere/blob/v4.5.4/assets/system/modules/prim.js

The nice thing about Sphere v2 is that screen is just another Surface - so you can draw stuff just as easily to any surface as you can to the screen.  At least, you're supposed to be able to.  scojin's case seems to be broken, and I can't figure out what's wrong based on reading his code.  I'll have to do some testing myself.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • scojin
  • [*]
Re: Surface Questions
Reply #5
Yeah, that's correct. I'm basically piecing together an image from a few smaller images. I am preprocessing it when the menu is first called so it doesn't have to run the code to build the image on each menu update.
I was just puzzled on why the text would appear correctly but not the images.

I was able to test around and recreate the situation. If I create the surface as an image, it displays whatever image was loaded, however if I 'add' an image afterwards, it doesn't. I'm able to have text appear and I can get graphic primitives to display(line,circle,fill,etc.), but images do not.

If it helps, my menu is basically a loop that 'refreshes' after a key is pressed.
Let me know if you need anymore info.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #6
I'll look into it, it's possible there's a bug in miniSphere.  What's weird is that you say primitives render fine, but not images.  If you look at the source code of the prim module:
prim.rect(): https://github.com/fatcerberus/minisphere/blob/v4.5.4/assets/system/modules/prim.js#L152-L165
prim.blit(): https://github.com/fatcerberus/minisphere/blob/v4.5.4/assets/system/modules/prim.js#L22-L37

rect and blit basically do the same thing under the hood, the only difference is whether the triangles are textured or not.  So this is quite the mystery.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: Surface Questions
Reply #7

He's using the Sphere v2 API (note the new Surface(...)).  Surfaces have no built-in primitives in Sphere v2, you're meant to use Galileo (i.e. Shape objects).  See:
https://github.com/fatcerberus/minisphere/blob/v4.5.4/docs/sphere2-api.txt#L913-L938


Oh damn, lol I'm becoming and old fogy in the community. lol
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #8


He's using the Sphere v2 API (note the new Surface(...)).  Surfaces have no built-in primitives in Sphere v2, you're meant to use Galileo (i.e. Shape objects).  See:
https://github.com/fatcerberus/minisphere/blob/v4.5.4/docs/sphere2-api.txt#L913-L938


Oh damn, lol I'm becoming and old fogy in the community. lol


No problem, hehe.  Everything works differently now, which is jarring at first, but being in the process of upgrading Spectacles to take advantage of all the Sphere v2 stuff now, I would say the changes I made are for the better.  I'm not really unhappy with any of them.  Combined with ES6, Sphere v2 really feels like a fully modern development environment now unlike Sphere 1.x which was really showing its age.

@scojin: I can verify your report, and I'm almost certain this is a bug.  I tried the following code:
Code: (javascript) [Select]

const prim = require('prim');
var surf = new Surface(100, 100);
var img = new Texture('images/titleCard.png');
prim.rect(surf, 10, 10, 50, 50, Color.Chartreuse);
prim.blit(surf, 0, 0, img);
var surfImg = surf.toTexture();
while (Sphere.run()) {
prim.blit(screen, 0, 0, surfImg);
screen.flip();
}


The rectangle is rendered, but the image is not.  Now I just have to figure out why.  By the way, Image was renamed to Texture a few versions ago so you should probably upgrade your miniSphere installation if you want your code to keep running ;)

edit: I found the bug.  When drawing to the screen, texture coordinates (U/V) are normalized and go from [0-1] bottom-to-top.  When drawing to a surface, however, they are in pixels and go from [0-w/h).  So what's actually happening is that prim.blit() correctly assumes the normalized coordinates, and only the top-left pixel of the image gets drawn.  I'm not sure what causes that yet, I'll have to study the Galileo code.
  • Last Edit: March 07, 2017, 01:02:52 am by Fat Cerberus
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #9
@scojin: Here's a monkey patch you can use until I fix the bug:
Code: (javascript) [Select]

require('prim').blit =
function blit(surface, x, y, image, mask)
{
mask = mask || Color.White;

var x1 = x;
var y1 = y;
var x2 = x1 + image.width;
var y2 = y1 + image.height;
var v1 = surface === screen ? 1 : 0;
var u2 = surface === screen ? 1 : image.width;
var v2 = surface === screen ? 0 : image.height;
var shape = new Shape([
{ x: x1, y: y1, u: 0,  v: v1, color: mask },
{ x: x2, y: y1, u: u2, v: v1, color: mask },
{ x: x1, y: y2, u: 0,  v: v2, color: mask },
{ x: x2, y: y2, u: u2, v: v2, color: mask },
], image, ShapeType.TriStrip);
shape.draw(surface);
}


The above patch won't work after the bug is fixed, so be sure to put it in a place you won't forget it exists.  Otherwise down the road you might wonder why your game suddenly broke after an update :P
  • Last Edit: March 07, 2017, 09:49:58 am by Fat Cerberus
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • scojin
  • [*]
Re: Surface Questions
Reply #10
Thanks, Cerberus! Major kudos!
Works like a charm.
  • Last Edit: March 07, 2017, 05:05:46 pm by scojin

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: Surface Questions
Reply #11
@scojin: I found the cause of the bug; it'll be fixed in miniSphere 4.5.5.  Allegro tracks shaders per render target.  When drawing Shapes to a surface, miniSphere was incorrectly applying the shader before switching the render target, meaning the shader got applied to the screen while the surface actually being drawn still used the Allegro default shader--which maps U/V to image pixels and thus causing prim.blit() to fail.  Very simple to fix. :)

edit: aaaaand miniSphere 4.5.5 is out now.
  • Last Edit: March 10, 2017, 02:35:04 am by Fat Cerberus
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • scojin
  • [*]
Re: Surface Questions
Reply #12
Magnifico!