Get the pixel size of an AnimatedSprite (gdscript) - godot

I am trying to clamp the player's position so that it's sprite doesn't go over the border, but apart from transform.scale there is no "size" indicator/variable.
position.x = clamp(position.x,0, screen_size.x - scale.x)

What you can do, if all sprites in the animation have the same size :
var current_animation : String = $AnimatedSprite.animation
var sprite_texture : Texture = $AnimatedSprite.frames.get_frame(current_animation, 0)
print(sprite_texture.get_size())
basically what I do here is getting the first texture in the current animation. and read out the size of the texture. This only works, of course, if all frames have the same size.
ALternativly you should be able to get the current frame by using $AnimatesSprite.frame.

Related

Lego style split screen camera in godot

I want to have lego style splitscreen camera with seamless transitions.
Anyone has any experience creating something like this? I thought of creating one normal camera and then another camera for second player that by default wouldn't be visible. Then, when i would want to show it, i would draw a triangle to split the screen and set it texture as camera #2 view.
I found this Unity implementation but i couldn't implement it in Godot. I've managed to create second viewport with it's own camera, but for some reason the view of the second camera is not showing anything. I'm thinking that the problem is that the world of the second viewport is different than the main viewport.
Source code can be found here.
I just setup a toy project to test this out and it turned out to be simpler than expected.
Here is an overview of the process and then code examples will follow.
Add one main camera
And a secondary camera with tree: Control > Viewport > Camera
Draw the shape of the split screen with Control using the draw_* api
Add a shader to Control that takes a texture and draws it at SCREEN_UV
Get the viewport texture from Viewport
Pass the viewport texture to the Control shader every frame.
Animate the split by animating and redrawing the Control shape.
I'm not sure how to do the border.
To make the split join you'll probably have to shift the Control shape by the thickness of border and then shrink that border as the cameras go towards each other. Use that distance between the players to calculate the border width.
The split border is also at an angle between the two players so when animating the shape you'll want to use that angle. This will make the joining of the viewport look smoother.
Control code:
extends Control
func _draw():
# in this case animate tl and bml to get the
# rotating split like effect in the lego game
var tl = Vector2()
var tr = rect_size
tr.y = 0
var br = rect_size
var bml = rect_size
bml.x /= 2.0
draw_polygon([tl, tr, br, bml, tl], [Color(), Color(), Color(), Color(), Color()], [])
func _process(d):
material.set_shader_param('viewport', $Viewport.get_texture())
Shader Code:
shader_type canvas_item;
uniform sampler2D viewport;
void fragment(){
COLOR=texture(viewport, SCREEN_UV);
}
I hope this helps get you started!
It is a complex effect with many parts so be warned.
I found that the easiest way is to create a separate scene with your viewports and cameras which will be your main scene and then add your game scene under it like this:
Spatial
Viewport1
Camera1
Viewport2
Camera2
GameScene
You should then be able to make a ColorRect with a shader material and send in the textures from each viewport:
shader_type canvas_item;
render_mode unshaded, cull_disabled;
uniform sampler2D viewport1;
uniform sampler2D viewport2;
void fragment() {
vec3 view1 = texture(viewport1, UV).rgb;
vec3 view2 = texture(viewport2, UV).rgb;
vec3 col = vec3(0);
// mix them in a satisfying way depending on distance and angle between cameras
// float mixVal = <your formula here>
// col = mix(view1, view2, mixVal)
COLOR = vec4(col, 0.0); // this may not work in Godot shaders
}
This is a great guide to get you started:
https://docs.godotengine.org/en/3.1/tutorials/viewports/using_viewport_as_texture.html

How to set relative position (oCoords) in FabricJs?

I have a Text in fabricJs. I set top and left.
This sets the aCoords properly to those values.
However the oCoords dont match. And the Text is not displayed at the right position.
I suspect that I need to set to oCoords somehow. So that the Text is displayed at the right pixel coordinates (top & left) on the canvas.
aCoords and oCoords are two different things and should not be in sync.
In your comment you speak about scaled canvas.
Top and Left are 2 absolute values that represent the position of the object on the canvas. This position match with the canvas pixels when the canvas has a identity transform matrix.
If you apply a zoom, this coordinates diverge.
To get the position of pixel 300,100 of the scaled canvas on the unscaled canvas, you need to apply some basic math.
1) get the transform applied to the canvas
canvas.viewportTransform
2) invert it
var iM = fabric.util.invertTransform(canvas.viewportTransform)
3) multiply the wanted point by this matrix
var point = new fabric.Point(myX, myY);
var transformedPoint = fabric.util.transformPoint(point, iM)
4) set the object at that point.

How to isolate a Phaser shader to a specific object/shape?

I'm using the Phaser framework. Here is the jsfiddle:
http://jsfiddle.net/Dillybob/u3mGL/13/
Here is where the filter is getting populated:
background = game.add.sprite(0, 0);
background.width = 800;
background.height = 600;
filter = game.add.filter('Fire', 800, 600);
filter.alpha = 0.0;
background.filters = [filter];
My line object is assigned to the variable drawnObject
So I assign that object to receive the filter like so:
drawnObject.filters = [filter];
But my line is now a red fiery square instead of being a line with a fiery background, why?
Firstly, be aware that drawnObject is actually a bitmap, which is rectangular shaped. It consists of white pixels, which build your line, and transparent pixels, which are taking the rest of bitmap space.
The filter you use is a pixel shader. Pixel shader describes instructions that GPU invokes for each pixel of a provided bitmap. In case of this shader, it creates fire effect based on some noise functions, but it doesn't take original bitmap into account. The original color of pixels is not preserved, it doesn't add to final effect in any way.
To achieve your expected result, you have to amend fragmentSrc in Fire.js, so that shader uses and mixes/blends original color into final pixel color and/or doesn't change pixel transparency.

androidplot background image shift

I'm trying to separate the background of the graph grid in 3 areas using this code:
int[] data = {0xff000000, 0x80008000, 0xff000000};
bgBitmap = Bitmap.createBitmap(data, 1, 3, Bitmap.Config.ARGB_8888);
RectF rect = plot.getGraphWidget().getGridRect();
BitmapShader myShader = new BitmapShader(
Bitmap.createScaledBitmap(bgBitmap, 1, (int) rect.height(), false),
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
plot.getGraphWidget().getGridBackgroundPaint().setShader(myShader);
So scaling a 3 pixel bitmap to the graph height and repeating it over the whole domain area.
However the resulting graph show that the background seems to be shifted up a bit.
It looks like the shift size is about equal to the domain label height.
How can I fix this?
Hm cannot post picture because of 'reputation' sigh.
Link to the example graph: http://marcel.mesa.nl/androidplot.png
I think you're running into the issue mentioned near the end of this thread. Essentially, the origin of the shader is the top-left corner of the screen, not the top-left corner of component for which the background is being drawn using the shader. The solution is to translate to the top-left point of the graphWidget like this:
RectF rect = plot.getGraphWidget().getGridRect();
Matrix m = new Matrix();
m.setTranslate(rect.left, rect.top);
shader.setLocalMatrix(m); // where shader is your shader instance

How to avoid fade-out on scaled CCSprite without cancelling anti-aliasing?

I have 3 sprites. Left edge, right edge, and repeating center which has 1 pixel width but is scaled up. The problem is that the scaled sprite fades out the farther away it is from the center:
I've tried using CCTexture's setAliasTexParameters but the result doesn't look good:
How do I get the antialiased looks in the first picture but without the fade out problem?
You could try this on the sprite:
// These parameters set the texture properties:
// minifying filter - linear interpolation,
// magnification filter - linear interpolation,
// texture repeat in S direction,
// texture repeat in T direction (*)
ccTexParams params = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
[sprite.texture setTexParams:&params];
// This explicitly sets the contentSize of the sprite to (10, 200),
// but also sets the "window to the texture" to this rectangle:
[sprite setTextureRect:CGRectMake(0, 0, 10, 200)];
You have to tweak these settings, but hope you get it.
You don't have to scale the sprite.
(*) For S and T check this: Difference between U V and S T texture coordinates

Resources