Could you please help with the endless background for the level?
I'm currently writing a primitive game using slick2d, the gameplay is similar to Mario.
I have two pictures - img1 and img2 (both 1280x480, while the screen resolution is 640x480).
Initially the X of the img2 is == (X of img1 + width of img1). I.e. its glued to the end of the img1.
When the img1 is out of the left screen border, it's X coordinate becomes img2X + imgWidth.
The logic looks right for me, but sometimes the pictures getting overstriked (a lot, approx 1/4 of the screen).
Is there any mistakes in the logic? Does the approach is good? Maybe there is more simple and right way to do so?
The pseudo-code look like below:
class BkgDrawer {
Image img1 = new Image("imgs/background/bkg1.png");
Image img2 = new Image("imgs/background/bkg2.png");
int img1Width = img1.getWidth(); //1280
int img2Width = img2.getWidth(); //1280
int screenResolution = game.getResolution; //640
Vector2f position1 = new Vector2f (0,0);
Vector2f position2 = new Vector2f (position1.x+img1.getWidth(), 0); //initially position2 is glued to the end of img1
public void render( ) {
if (position1.x + img1Width < 0) { //the img is over the left border of the screen
position1.x = position2.x + img2Width; //glue it to the end of img2
}
//the same for the img2
if (position2.x + img2Width < 0) { //the img is over the left border of the screen
position2.x = position1.x + img2Width; //glue it to the end of img2
}
img1.draw(position1.x, position1.y);
img2.draw(position2.x, position2.y);
//move coordinate to get the background moving.
position1.x -= MOVING_STEP;
position2.x -= MOVING_STEP;
}
}
Sorry for the lot of text and thanks
I have found only one bug and it will only have an affect if the two images have different widths: Your two if-statements use the same width img2Width
You may have noticed that you have duplicate code to handle the rendering and repositioning of each background. Might I suggest that you refactor the background code into a Background class that contains the background image, position, and and update method that repositions it by MOVING_STEP. You will avoid mistakes like the one I mentioned above.
Related
I have never scripted in photoshop before, so I am wondering if this is possible. The following is currently done manually for over than 300 files. The next time round is for 600 files, therefore I am looking into automating it.
Steps:
Make Image Size to 54pixels Hight and 500px Width -- Found that this is doable.
Align Image Left.
Create a text layer and insert text -- Found that this is doable.
Align Text layer 1px to the right of the image.
Trim empty space.
Would appreciate any help and pointers. Thanks.
This script will get you started: Note that in your request you didn't mention what what the original image was going to be and shrinking it to 500 x 54 is going to stretch it one way or another. Step 2, Align the image left, was omitted as you didn't mention what you are aligning this image to. I suspect you are dealing with a large image and what to shrink it down (as long as it's not smaller than 500 x 54) and work from there. I've also omitted stage 4 as I've hard coded the position of the text to be 1 px from the right hand edge (and it vertically centered with Arial font size 18)
Anhyoo.. you should be able to alter the script to your needs.
// set the source document
srcDoc = app.activeDocument;
//set preference units
var originalRulerPref = app.preferences.rulerUnits;
var originalTypePref = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.POINTS;
app.preferences.typeUnits = TypeUnits.POINTS;
// resize image (ignoring the original aspect ratio)
var w = 500;
var h = 54;
var resizeRes = 72;
var resizeMethod = ResampleMethod.BICUBIC;
srcDoc.resizeImage(w, h, resizeRes, resizeMethod)
//create the text
var textStr = "Some text";
createText("Arial-BoldMT", 18.0, 0,0,0, textStr, w-1, 34)
srcDoc.activeLayer.textItem.justification = Justification.RIGHT
//set preference units back to normal
app.preferences.rulerUnits = originalRulerPref;
app.preferences.typeUnits = originalTypePref;
//trim image to transparent width
app.activeDocument.trim(TrimType.TRANSPARENT, true, true, true, true);
// function CREATE TEXT(typeface, size, R, G, B, text content, text X pos, text Y pos)
// --------------------------------------------------------
function createText(fface, size, colR, colG, colB, content, tX, tY)
{
// Add a new layer in the new document
var artLayerRef = srcDoc.artLayers.add()
// Specify that the layer is a text layer
artLayerRef.kind = LayerKind.TEXT
//This section defines the color of the hello world text
textColor = new SolidColor();
textColor.rgb.red = colR;
textColor.rgb.green = colG;
textColor.rgb.blue = colB;
//Get a reference to the text item so that we can add the text and format it a bit
textItemRef = artLayerRef.textItem
textItemRef.font = fface;
textItemRef.contents = content;
textItemRef.color = textColor;
textItemRef.size = size
textItemRef.position = new Array(tX, tY) //pixels from the left, pixels from the top
}
Everything you listed is doable in a script. I suggest you start by reading 'Adobe Intro To Scripting' in your ExtendScript Toolkit program files directory (e.g. C:\Program Files (x86)\Adobe\Adobe Utilities - CS6\ExtendScript Toolkit CS6\SDK\English)
Here is the situation. In my app I have an overlay layer that is composed of a transparent PNG. I have replaced the hitarea for the png with a 1x1 image using the following code:
[Bindable]
[Embed(source = "/assets/1x1image.png")]
private var onexonebitmapClass:Class;
private function loadCompleteHandler(event:Event):void
{
// Create the bitmap
var onexonebitmap:BitmapData = new onexonebitmapClass().bitmapData;
var bitmap:Bitmap;
bitmap = event.target.content as Bitmap;
bitmap.smoothing = true;
var _hitarea:Sprite = createHitArea(onexonebitmap, 1);
var rect:flash.geom.Rectangle = _box.toFlexRectangle(sprite.width, sprite.height);
var drawnBox:Sprite = new FlexSprite();
bitmap.width = rect.width;
bitmap.height = rect.height;
bitmap.x = -loader.width / 2;
bitmap.y = -loader.height / 2;
bitmap.alpha = _alpha;
_hitarea.alpha = 0;
drawnBox.x = rect.x + rect.width / 2;
drawnBox.y = rect.y + rect.height / 2;
// Add the bitmap as a child to the drawnBox
drawnBox.addChild(bitmap);
// Rotate the object.
drawnBox.rotation = _rotation;
// Add the drawnBox to the sprite
sprite.addChild(drawnBox);
// Set the hitarea to drawnBox
drawnBox.hitArea = _hitarea;
}
private function createHitArea(bitmapData:BitmapData, grainSize:uint = 1):Sprite
{
var _hitarea:Sprite = new Sprite();
_hitarea.graphics.beginFill(0x900000, 1.0);
for (var x:uint = 0; x < bitmapData.width; x += grainSize)
{
for (var y:uint = grainSize; y < bitmapData.height; y += grainSize)
{
if (x <= bitmapData.width && y <= bitmapData.height && bitmapData.getPixel(x, y) != 0)
{
_hitarea.graphics.drawRect(x, y, grainSize, grainSize);
}
}
}
_hitarea.graphics.endFill();
return _hitarea;
}
This is based off the work done here: Creating a hitarea for PNG Image with transparent (alpha) regions in Flex
Using the above code I am able to basically ignore the overlay layer for all mouse events (click, double click, move, etc.) However, I am unable to capture the right click (context menu) event for items that are beneath the overlay.
For instance I have a spell check component that checks the spelling on any textitem and like most other spell checkers if the word is incorrect or not in the dictionary underlines the word in red and if you right click on it would give you a list of suggestions in the contextmenu. This is working great when the text box is not under the overlay, but if the text box is under the overlay I get nothing back.
If anyone can give me some pointers on how to capture the right click event on a textItem that is under a transparent png that would be great.
How does one go about giving a title to the axis in prefuse scatter plot?
At the moment my code reads the data from the file and a range for both x and y axis works in the code. All I need to do now is to add titles/names for the axis. The code I have at the moment shows:
//set up the actions
AxisLayout xaxis = new AxisLayout(group, "GD",
Constants.X_AXIS, VisiblePredicate.TRUE);
AxisLayout yaxis = new AxisLayout(group, POINTS,
Constants.Y_AXIS, VisiblePredicate.TRUE);
//yaxis.setScale(Constants.LOG_SCALE);
yaxis.setRangeModel(receiptsQ.getModel());
receiptsQ.getNumberModel().setValueRange(0,120,0,120);
xaxis.setLayoutBounds(m_dataB);
yaxis.setLayoutBounds(m_dataB);
// sets group,axis,values,bounds
AxisLabelLayout ylabels = new AxisLabelLayout("ylab", yaxis, m_ylabB);
NumberFormat nf= NumberFormat.getInstance();
nf.setMaximumFractionDigits(0);
ylabels.setNumberFormat(nf);
// AxisLabelLayout xlabels = new AxisLabelLayout("goal diff", xaxis, m_xlabB, 15);
AxisLabelLayout xlabels = new AxisLabelLayout("xlab",xaxis,m_xlabB,5);
// vis.putAction("xlabels", xlabels);
vis.putAction("xlabels", xlabels);
You have to do it by hand. I've done this and my code is open source, so you're welcome to take a look at it:
https://github.com/brycecr/msmexplorer/blob/acacia/MSMExplorer/src/edu/stanford/folding/msmexplorer/util/axis/AxisRotateRenderer.java
https://github.com/brycecr/msmexplorer/blob/acacia/MSMExplorer/src/edu/stanford/folding/msmexplorer/util/axis/AxisLabelLabelLayout.java
In the label renderer, all the labels are drawn as a combination of a line and a label. In this class, we just add an additional item to the layout with our graph.
This is not super clean at all...in particular, a line (actually one pixel) is still rendered for the label, but I'm lazy and this suits my needs...I think you could improve this if necessary, but you'd probably need to reach into the axis renderer and make it draw no line for your label items.
Let me know if you have any questions about the operation of this.
#Override
public void run(double frac) {
super.run(frac);
setLabPos(item, length/2.0d + width, bounds);
}
/**
* Set the layout values for an axis label item.
*/
protected void setLabPos(VisualItem item, double xOrY, Rectangle2D b) {
switch (getAxis()) {
case Constants.X_AXIS:
xOrY = super.isAscending() ? xOrY + b.getMinX() : b.getMaxX() - xOrY;
PrefuseLib.updateDouble(item, VisualItem.X, xOrY);
PrefuseLib.updateDouble(item, VisualItem.Y, b.getMaxY() + label.getFont().getSize()/3.0d + gridLab.getFont().getSize());
PrefuseLib.updateDouble(item, VisualItem.X2, xOrY);
PrefuseLib.updateDouble(item, VisualItem.Y2, b.getMaxY() + label.getFont().getSize()/3.0d + gridLab.getFont().getSize());
break;
case Constants.Y_AXIS:
xOrY = super.isAscending() ? b.getMaxY() - xOrY - 1 : xOrY + b.getMinY();
PrefuseLib.updateDouble(item, VisualItem.X, b.getMinX());
PrefuseLib.updateDouble(item, VisualItem.Y, xOrY);
PrefuseLib.updateDouble(item, VisualItem.X2, b.getMinX());
PrefuseLib.updateDouble(item, VisualItem.Y2, xOrY);
}
}
}
How to draw a triangle in a math graph which displays X and Y axis.
To draw shapes using ActionScript2, you can use the moveTo() and lineTo() methods of the MovieClip object. You can specify line colour and thickness with lineStyle(), or make a solid shape using beginFill() and endFill().
So to draw your graph and triangle you could do the following steps:
Make a movieClip named "graph"
Define how big your graph should be (using the flash.geom.Rectangle object)
Draw a grey background using graph.beginFill(grey) and then moveTo() and lineTo()
Draw some blue lines at regular intervals for a grid
Draw the X and Y axes on the side and bottom of your grid
Make a second movieClip named "shape"
Pick 3 random points: moveTo(point1), lineTo(point2), lineTo(point3), lineTo(point1)
Here's how the code might look:
import flash.geom.Point;
import flash.geom.Rectangle;
function drawGraph(mc:MovieClip, rect:Rectangle):Void {
//this is a function to draw the graph
//draw the background
mc.beginFill(0xF8F8F8);
mc.moveTo(rect.left, rect.bottom);
mc.lineTo(rect.left, rect.top);
mc.lineTo(rect.right, rect.top);
mc.lineTo(rect.right, rect.bottom);
mc.lineTo(rect.left, rect.bottom);
mc.endFill();
//draw a grid
var unit:Number = 20;
mc.lineStyle(1, 0x0000FF, 20, true, "none", "round", "round");
var i:Number=rect.x;
do {
i=i+unit;
mc.moveTo(i, rect.bottom);
mc.lineTo(i, rect.top);
} while (i<rect.right);
i=rect.bottom;
do {
i=i-unit;
mc.moveTo(rect.left, i);
mc.lineTo(rect.right,i);
} while (i>rect.top);
//draw the axes
mc.lineStyle(2, 0x808080, 100, true, "none", "round", "round");
mc.moveTo(rect.left, rect.bottom);
mc.lineTo(rect.left, rect.top);
mc.moveTo(rect.left, rect.bottom);
mc.lineTo(rect.right, rect.bottom);
}
function randomPoint(rect:Rectangle):Point {
//this is a function which returns a random point within rect
var p:Point = new Point(rect.x+Math.random()*rect.width, rect.y+Math.random()*rect.height);
return p;
}
function drawTriangle(mc:MovieClip, rect:Rectangle):Void {
//this is a function to draw the triangle
// pick 3 random points within rect
var p1:Point = randomPoint(rect);
var p2:Point = randomPoint(rect);
var p3:Point = randomPoint(rect);
//connect the points to make a triangle
mc.lineStyle(3, 0xFF0000, 100, true, "none", "round", "round");
mc.moveTo(p1.x, p1.y);
mc.lineTo(p2.x, p2.y);
mc.lineTo(p3.x, p3.y);
mc.lineTo(p1.x, p1.y);
}
//make the 'graph' clip:
var myGraph:MovieClip = this.createEmptyMovieClip("myGraph", this.getNextHighestDepth());
//define the graph size:
var myRect:Rectangle = new Rectangle(50,50,300,300);
drawGraph(myGraph,myRect);//draw the graph
var myShape:MovieClip = this.createEmptyMovieClip("myShape", this.getNextHighestDepth());//make the 'shape' clip
drawTriangle(myShape,myRect);//draw a random triangle
//add a function to draw a new triangle when the graph is clicked:
myGraph.onRelease = function() {
myShape.clear();//erase the old triangle
drawTriangle(myShape,myRect);//draw a new one
}
You can click the graph to generate a new random triangle.
(source: webfactional.com)
It sounds like you need to know how the drawing API works in Flash. Your question is kind of vague, but this might help to get you started - google "Flash Drawing API" for more information.
var point1:Point = new Point (0, 0);
var point2:Point = new Point (25, -50);
var point3:Point = new Point (50, 0);
var s:Sprite = new Sprite();
s.graphics.lineStyle(1, 0xff0000);
s.graphics.beginFill(0x000000);
s.graphics.moveTo(point1.x, point1.y);
s.graphics.lineTo(point2.x, point2.y);
s.graphics.lineTo(point3.x, point3.y);
s.graphics.lineTo(point1.x, point1.y);
s.graphics.endFill();
s.graphics.lineStyle(0);
s.x = (stage.stageWidth - s.width) / 2;
s.y = ((stage.stageHeight - s.height) / 2) + 50;
addChild(s);
I hope that helps, let me know if you have any questions.
NOTE: This solution is using ActionScript 3. If you need AS2 this won't work, and off the top of my head I don't know how to help but you might just try googling "AS2 Drawing API" or something to that effect.
Whether I use XTextFormatter or not, I get the same error about the LayoutRectangle having to have a height of 0 or something like this.
new PdfSharp.Drawing.Layout.XTextFormatter(_gfx).DrawString(text
, new PdfSharp.Drawing.XFont(fontName, fontSize, (PdfSharp.Drawing.XFontStyle)fontStyle)
, new PdfSharp.Drawing.XSolidBrush(PdfSharp.Drawing.XColor.FromArgb(foreColour))
, new PdfSharp.Drawing.XRect(new PdfSharp.Drawing.XPoint(xPos, yPos), new PdfSharp.Drawing.XPoint(xLimit, yLimit))
, PdfSharp.Drawing.XStringFormats.Default);
fontStyle is of type System.Drawing.FontStyle
foreColour is of type System.Drawing.Color
I have already predefined _gfx from a PdfPage with Orientation = Landscape, Size = Letter
xPos and yPos are parameters of type double, the same with xLimit and yLimit.
I get the runtime error that the
LayoutRectangle must have a height of
zero (0)...
Per definition a rectangle is meant to have a height, otherwise call it a line! I don't get it!...
I tried with the XGraphics.DrawString() method directly, and I get the same error. It seems that I can't use the LayoutRectangle but have to manage that the text fit within the desired area manually.
var textFont = new PdfSharp.Drawing.XFont(fontName, fontSize, (PdfSharp.Drawing.XFontStyle)fontStyle);
while (xPos + _gfx.MeasureString(text, textFont).Width > xLimit)
textFont = new PdfSharp.Drawing.XFont(fontName, --fontSize, (PdfSharp.Drawing.XFontStyle)fontStyle);
while (yPos + _gfx.MeasureString(text, textFont).Height > yLimit && fontSize > 0)
textFont = new PdfSharp.Drawing.XFont(fontName, --fontSize, (PdfSharp.Drawing.XFontStyle)fontStyle);
_gfx.DrawString(text
, textFont
, new PdfSharp.Drawing.XSolidBrush(PdfSharp.Drawing.XColor.FromArgb(foreColour))
, new PdfSharp.Drawing.XPoint(xPos, yPos));
Though the yPos variable value is the exact same value!
*yPos = Page.Height * .4093, either 40,93% of the page's height.*
Herewith an example of what I try to do:
"Hello World!" "Hello
World!"
And here is what I get:
"Hello World!"
"Hello World!"
And because of different printing area limits and size of the font and the different font style, I can't just write these into one simple sentence including the correct number of spaces.
Quoting error messages exactly helps others to help you.
The error message reads:
DrawString: With XLineAlignment.BaseLine the height of the layout rectangle must be 0.
The text will be aligned at a line, therefore height must be 0. Yes, that's a line.
Use a different alignment if you specify a rectangle.
The TextLayout sample shows how to format text.
The Graphics sample also shows how to layout text (single lines of text, no automatic line breaks; the technique shown in the TextLayout sample handles line breaks automatically using the XTextFormatter class).
While trying to figure out how text positioning works with PdfSharp, I noticed that the DrawString() method writes on top of the Y coordinate that we specify.
If I wish to write at (0, 100)(x, y), this points to the lower-left corner while I thought this was the top-left corner coordinates. As a result, the text string Y coordinate that I should have specified is 100 + string.Height * .6.
PdfDocument pdfDoc = new PdfDocument();
PdfPage pdfPage = new pdfPage();
pdfPage.Size = PageSize.Letter;
pdfPage.Orientation = Orientation.Landscape;
pdfDoc.Pages.Add(pdfPage);
double posX = 0;
double posY = pdfPage.Height * .4093;
string helloString = "Hello"
string worldString = "World!"
XFont helloFont = new XFont("Helvetica", 25, XFontStyle.Regular);
XFont worldFont = new XFont("Helvetica", 270, XFontStyle.Bold);
using(var pdfGfx = XGraphics.FromPdfPage(pdfPage)) { // assuming the default Point UOM
XSize helloStringSize = pdfGfx.MeasureString(helloString, helloFont);
XSize worldStringSize = pdfGfx.MeasureString(worldString, worldFont);
pdfGfx.DrawString(helloString
, helloFont
, XBrushes.Black
, posX
, posY + helloStringSize.Height * .6
, XStringFormats.Default);
pdfGfx.DrawString(worldString
, worldFont
, XBrushes.Black
, pdfPage.Width * .3978
, posY + (worldStringSize.Height + helloStringSize.Height) * .6
, XStringFormats.Default);
}
You'll perhaps wonder why I only add 60% of the string size when I want to get my string written below my Y coordinate? That is because the full height of the font includes somekind of leap on top. So, the computing result will not be what is expected. On the other hand, you don't have to care about a leap if you need one. In my particular case, I don't require leap, so I must take it off the string's height.
If you feel like my explanation needs more accurate details, please feel free to either add them as comments or keep me informed so that I may include them.
Thanks!