I just developed a game using Cocos2D,it is so easy to move an object on the screen using Cocos such as MoveTo. But what about in Cocoa? How can I make an object move from point A to point B easily? Could anyone help? I really appreciate any helps. This is the code i used to make an object move in Cocos. How can I convert this to Cocoa, I mean the way to make a thing move in Cocoa.
Sprite *logo = [Sprite spriteWithFile:#"logo.png"];
logo.position = CGPointMake (240 , -10);
[self addChild:logo];
id actionTo = [MoveTo actionWithDuration:1.0f position:ccp(240, 55)];
[sexyTrainning runAction:actionTo];
Depends on what kind of object you want to move.
Using Core Animation you could move a CALayer along an arbitrary path using the path property of CAKeyframeAnimation
More examples here.
Related
I'm trying to import Agent Geometry Kit (https://github.com/hfossli/AGGeometryKit) which is written in Objective-C into a Swift project.
I start by copying all the source files into my project, then I create a bridge header file in which I import all the header files I just added (which looks like this https://gist.github.com/JeanCParis/97dc6c27c70a4f00dbb0)
My problem is that although all the imported classes and structs are now available in my project, unions like AGKQuad are not.
Am I doing something wrong, or are unions not usable in Swift and if so how can I best bypass this problem ? Many thanks in advance !
Jean-Christophe
EDIT : I'm still a neophyte in developing on IOS, but can't I just make a Objective-C class which I can call from my Swift project to "do the job" and send me the result I'm looking for ? I tried to do just that and it unfortunately does not give me the expected result, although it might be that I don't yet fully understanding how Agent Geometry Kit works (what the method does comes from the readme file on github)
#implementation DoTheJob
- (UIImageView*)DoDaJob:(UIImage*)image {
UIImageView *view = [[UIImageView alloc] initWithImage:image];
[view.layer ensureAnchorPointIsSetToZero]; // set the anchor point to [0, 0] (this method keeps the same position)
AGKQuad quad = view.layer.quadrilateral;
quad.br.x += 600; // shift bottom right x-value with 20 pixels
quad.br.y += 500; // shift bottom right y-value with 50 pixels
view.layer.quadrilateral = quad; // the quad is converted to CATransform3D and applied
printf("DoingDaJob");
return view;
}
#end
Should this work in principle ?
C unions are apparently not supported (yet).
The code I posted in my edited question works just fine, even though it might not be the optimal solution, I was simply misunderstanding how this library works.
I'm making a tool that will pull data from a .csv and create a grid of images with captions [like "This"] in Cocoa, then export that to a PDF. I do not need to actually display the view, just save a file. As a complete beginner to drawing programmatically, I have some questions about the process:
What class should I use? I'm assuming NSView, but like I said I've never done this before so I'm not sure.
Do I need to specify the pixel coordinates for every single object, or can I make each object relative to another in some way?
How do I create separate pages for the view?
Keep in mind that I read the Apple guides, and while it had some helpful tidbits, overall it was unusually hard for me to comprehend. If someone could explain in layman's terms what I need to know it would be very appreciated! Thank you in advance.
Have a look at NSCollectionView
Overview
NSCollectionView class displays an array of content as a grid of
views. The views are specified using the NSCollectionViewItem class
which makes loadings nibs containing the view easy, and supports
bindings
There are lots of tutorials.
Including:
Cocoa Programming L42 - NSCollectionView
And
Apples own quick guide to Collection Views
And maybe also look at NSDocuments
Overview
The NSDocument abstract class defines the interface for OS X
documents. A document is an object that can internally represent data
displayed in a window and that can read data from and write data to a
file or file package. Documents create and manage one or more window
controllers and are in turn managed by a document controller.
Documents respond to first-responder action messages to save, revert,
and print their data.
Conceptually, a document is a container for a body of information
identified by a name under which it is stored in a disk file. In this
sense, however, the document is not the same as the file but is an
object in memory that owns and manages the document data. In the
context of AppKit, a document is an instance of a custom NSDocument
subclass that knows how to represent internally, in one or more
formats, persistent data that is displayed in windows.
A document can read that data from a file and write it to a file. It
is also the first-responder target for many menu commands related to
documents, such as Save, Revert, and Print. A document manages its
window’s edited status and is set up to perform undo and redo
operations. When a window is closing, the document is asked before the
window delegate to approve the closing.
NSDocument is one of the triad of AppKit classes that establish an
architectural basis for document-based apps (the others being
NSDocumentController and NSWindowController).
Figured it out a few days ago, thought I'd come back to answer for anyone else with the same question.
What class should I use? I'm assuming NSView, but like I said I've never done this before so I'm not sure.
NSView is in fact the class I used to draw each page.
Do I need to specify the pixel coordinates for every single object, or can I make each object relative to another in some way?
I did end up specifying the pixel coordinates for each image on the grid (plus its caption), but it was easy to calculate where they should be placed once I learned the size of a 8.50 x 11 inch page in points. The next challenge was drawing them in a for loop rather than having to explicitly declare each possible NSRect. Here's my code in drawRect:
// Declared elsewhere: constants for horizontal/vertical spacing,
// the width/height for an image, and a value for what row the image
// should be drawn on
for (int i = 0; i < [_people count]; i++) {
float horizontalPoint = 0.0; // What column should the image be in?
if (i % 2 != 0) { // Is i odd? (i.e. Should the image be in the right column?)
horizontalPoint += (imageWidth + horizontalSpace); // Push it to the right
}
NSRect imageRect = NSMakeRect(horizontalSpace + horizontalPoint, verticalSpace + verticalPoint,
imageWidth, imageHeight);
// Draw the image with imageRect
if (i % 2 != 0) { // Is i odd? (i.e. Is the current row drawn?)
verticalPoint = (imageRect.origin.y + imageRect.size.height); // Push the row down
}
}
I do realize that I could've coded that more efficiently (e.g. making a BOOL for i % 2 != 0), but I was rushing the whole project because my friend who needed it was on a deadline.
How do I create separate pages for the view?
With some googling, I came up with this SO answer. However, this wasn't going to work unless I had one big view with all the pages concatenated together. I came up with a way to do just that:
// Get an array of arrays containing 1-6 JANPerson objects each using data from a parsed in .csv
NSArray *paginatedPeople = [JANGridView paginatedPeople:people];
int pages = [JANGridView numberOfPages:people];
// Create a custom JANFlippedView (just an NSView subclass overriding isFlipped to YES)
// This will hold all of our pages, so the height should be the # of pages * the size of one page
JANFlippedView *view = [[JANFlippedView alloc] initWithFrame:NSMakeRect(0, 0, 612, 792 * pages)];
for (int i = 0; i < [paginatedPeople count]; i++) { // Iterate through each page
// Create a custom JANGridView with an array of people to draw on a grid
JANGridView *gridView = [[JANGridView alloc] initWithFrame:NSMakeRect(0, 0, 612, 792) people:paginatedPeople[i]];
// Push the view's frame down by 792 points for each page drawn already
// and add it to the main view
gridView.frame = NSMakeRect(0, 792 * i, gridView.frame.size.width, gridView.frame.size.height);
[view addSubview:gridView];
}
I apologize if this is hard to understand for anybody; I'm better at talking through my process than writing! I welcome anyone to ask for help if there's something unclear, or edit if they can make it better.
NsView; so tis a mac app?
CGPointMake Returns a point with the specified coordinates. i.e. placing an image in a specific spot on the screen using matrices i.e.
layer.position = CGPointMake ([self view].bounds.size.width /2, [self view].bounds.size.height /3 );
(this example is oriented around core animation (moving objects on screen so please don't take it too literally) hence the layer attribute)
Also this line
layer.bounds= CGRectMake (100,100,1000,1000);
specifies a rectangles boundaries (rectangles can be filled with images and custom data using a bridge i believe; like this):
UIImage *image2 = [[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"flogo#2x"ofType:#"png"]];
layer.contents = (__bridge id)image2.CGImage;
Also i believe the cgdrawrect class when combined with matrices i.e. (x,x,x,x) can draw custom rectangles as in your image.
But hopefully you catch my drift with drawing and substituting images . The Core graphics framework will probably be used here. ( my whole answer used core animation as a reference)
I have created a SpriteKit game for shape recognition where there are two same shapes one is at lower part of the scene while other one which is to be matched is at upper side of the scene. I am creating these shapes by calling method from other class which contain code to create the shape.
I am able to do all the things in the proper way and works fine. But I am unable to find that how to make upper side shapes static. Mean user must be able to drag only lower side shapes to upper side shapes for matching but the should not be able to drag upper side shapes to match with lower side shapes. I have so far searched in SpriteKit Programming Guide by Apple but there is no such clue in that that helps me perform the above mentioned task.
Please help me if anyone can.
Easy way to do is set their name when you create them. Use a constant is any easy way so you ensure you are adding / checking the right name.
static NSString * const kCanMoveMe = #"movable";
static NSString * const kCanNotMoveMe = #"not-movable";
// for example
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:imageName];
sprite.name = kCanMoveMe
SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithImageNamed:imageName];
sprite.name = kCanNotMoveMe
Then when you touch check the name and then you know if you can move it or not.
You can also leverage the SKNode .userData property to store custom node data for the actual sprite, in your situation if it is movable or not or any other game specific data.
More info here: Apple documentation about the userData property
I suggest subclassing the SKSpriteNode and adding a isMoveable BOOL property to designate if it is able to be moved.
The other answers will definitely work, but both lack advantages of your property being named appropriately and accessible via the Xcode code completion capabilities.
For example in Xcode you would type mySprite.i and the isMoveable BOOL property would be available to choose for code completion.
I add my sprite frames to CCSpriteFrameCache. Then I create a CCSpriteBatchNode with my desired image file.
This is what I don't quite understand:
When I make a CCSprite, if I want to take advantage of the CCSpriteBatchNode, I need to initialize the CCSprite with [CCSprite spriteWithBatchNode: rect:]? But if that's the case, I don't see how am I taking advantage of CCSpriteFrameCache to get the frames, since now I would be manually making the rect.
So I guess I use [CCSprite spriteWithSpriteFrameName:] and then I add this sprite to the batch node. But I am still unsure.
You should use:
CCSprite *sp = [CCSprite spriteWithSpriteFrameName:#"monster.png"];
The .plist that you specified in the SpriteFrameCache will take care of the frames for you.
Then you create the sprite and add to the batch.
If you create the batchnode with a file called "myArt.png", you CAN ONLY add a sprite to it that is contained inside "myArt.png".
Hope it helps!
According to what I've learned of cocos2d. SpriteFrameCache and SpriteBatchNode have the same result but are used differently and can notice a slight performance difference if your game is very big...
CCSpriteFrameCache loads your frames according to when they are called by their named according to the plist file it was given. The atlas associated with the plist has to be added to the project as well or else the frames will be called but nothing will be found to be drawn. The Plist is like the address of where the image is located inside the image atlas.
The good part of CCSpriteFrameCache is that the code is neater, and smaller than CCSpriteBatchNode method, at the cost that for every call of that frame, it goes to that specific atlas and draws it.
CCSpriteBatchNode, on the other hand, loads the atlas and loads it in one draw call. This is efficient because it reduces the amount of times the draw has to be done per need in the game. The only difficulty here is that you need to do math for the rectangles of each sprite in the atlas. This is because lets say your atlas is of 2 actions of a character, the atlas image file has a size of 1024x1024, and each sprite has a size of 128x128. so you would do the math to get each rectangle for the whole jump action for example.(This is where .plist come in handy to avoid doing such math)
The code gets complicated as you can see but it will only do one call, making it performance-wise your best call.
Another way to use CCSpriteBatchNode is to have different static sprites and you would just do one draw call for those multiple static images or sprites.
If you need example code just ask, I would be more than happy to provide it.
Update: Adding Link for SpriteBatchNode and an Example of my own.
SpriteBatchNode:
Example using SpriteBatchNode with Ray Wenderlich
I believe in this guy, and I have learned alot of Cocos2d from his tutorials. I would suggest you to read other of his tutorials.
In a nutshell, CCSpriteBatchNode is the exact same process we did below with the CCSpriteFrameCache the ONLY difference and its that you add the Sprite Child Node to the CCSpriteBatchNode and not the Layer, BUT you do Add the CCSpriteBatchNode to the Layer.
This is the hard concept that new comers to Cocos2d get entangled at.
SpriteFrameCache:
The SpriteFrameCache I couldn't find a good example so here is one simple one.
//By doing this your sprites are now in the cache ready to be used
//by their names declared in the .plist file.
-(void) loadingSprites:(NSString*) plistName {
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:plistName];
}
-(id)initGameLayer {
//CCSprite accepts CCSpriteFrame and your img is now ready to be displayed.
//However is still not drawn yet.
CCSprite * mySprite = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:framename];
//set a position if desired
//20 pixels to the right and 0 pixels to the top.
mySprite.position = CGPointMake(20,0);
//Now the Image has been drawn, making 1 draw call.
[self addChild:mySprite];
}
It is noteworthy to point out that CCSpriteBatchNode makes just 1 drawcall, HOWEVER all the sprites being added to the batchnode have to be part of the same SpriteAtlas.
And using SpriteFrameCache only its easier and simpler, but for every child added to the layer it means +1 draw call is being done.(This is the downside, performance)
So if you add 10 Sprites to the layer with SpriteFrameCache you will have 10 drawcalls.
However if you implement the SpriteBatchNode and add those 10 Sprites in the CCSpriteBatchNode instead and just add that CCSpriteBatchNode to the layer, you will have the same 10 sprites added but only ONE draw call will be done. Hence the Performance difference(for the best) will be significant in larger games.
Hope it helps, Cheers!
So here's what I'm trying to do:
Create a sprite from the atlas I read into CCSpriteFrameCache (working fine.)
Add an animation to the sprite - I can also get this working fine but...
The animation is created by loading up a number of CCSpriteFrames, which in turn are reading in CCTextures from a shared CCTextureCache as their assets. It works, but I'm not convinced it's the best way. Seems like I should be loading those CCSpriteFrames with elements of the atlassprite I already loaded in CCSpriteFrameCache.
Question is: is there a method or way of loading those CCSpriteFrames with CCSprites named in the frames of CCSpriteFrameCache?
Open to the idea that I'm going about this wrong. Thanks for any tips.
Code here:
CCAnimation *thingAnimation = [CCAnimation animationWithName:#"wiggle" delay:0.1f];
//this works but I want to get the CCTexture from CCSpriteFrameCache....
aTexture = [[CCTextureCache sharedTextureCache] addImage:#"moon.png"];
//because CCSpriteFrame will only accept a CCTexture
frame1 = [CCSpriteFrame frameWithTexture:aTexture rect:CGRectMake(0, 0, aTexture.pixelsWide, aTexture.pixelsHigh) offset:ccp(0,-40)];
[thingAnimation addFrame:frame1];
I suppose if you knew this already, you think it was a pretty stupid question. I found the answer here:
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:animation
Basically to do animation from an atlas and a plist, you need to be able to work with CCSpriteSheet, CCSprite, CCSpriteFrame, CCSpriteFrameCache and CCAnimation.
You create the CCSpriteSheet first. Then you create the CCSpriteFrameCache from a plist. Then you can create CCSprites and CCSpriteFrames at will; the CCSpriteFrames feed into the CCAnimation.
That's my take, anyhow. Any better way, lemme know.