I have a SKShapenode creating a line that detects collisions but only for the first line. I can continue drawing lines after but only the first line has physics properties. How do I make an array of shape nodes that all will detect collisions? Drawing is working and didBeginContact method is working fine for first collision so I think the problem is in applying the physics category to an array and not just the first one drawn.
let line = SKShapeNode()
line.path = path
line.strokeColor = UIColor.blackColor()
line.lineWidth = 5
[self.addChild(line)]
lineArray.append(line)
line.physicsBody = SKPhysicsBody(edgeChainFromPath: path)
line.physicsBody?.dynamic = false
line.physicsBody?.categoryBitMask = PhysicsCategory.Lines
line.physicsBody?.contactTestBitMask = PhysicsCategory.Ball
line.physicsBody?.collisionBitMask = PhysicsCategory.Ball
line.physicsBody?.usesPreciseCollisionDetection = true
Related
I'm programming a task for a research study. The problem I have is the following: I have a dictionary with names and with one picture per cell. Like that:
nameCues1 = {'Lisa','Anna', 'Sarah', 'Nina', 'resized_1.jpg' };
nameCues2 = {'Emma', 'Lena', 'Gabi', 'Steffi', 'resized_2.jpg' };
I have loaded them into a cell array, created a random sequence:
nameCuesAll = {nameCues1,nameCues2};
randSeq3 = nameCuesAll(randperm(size(nameCuesAll,2)));
Then I loop over it to read in the names of the dictionary and the corresponding picture:
for i = 1:numel(nameCuesAll)
pics3{i} = imread(randSeq3{i}{1,5});
ind{i}=randSeq3{i}(randperm(numel(randSeq3{i})));
end
Then I prompt it on the screen via Psychtoolbox, a toolbox specialized in creating tasks for research, for those who don't know:
for j = 1:4
% (left out unnecessary other functions)
DrawFormattedText(window,ind{i}(j), 'center', 'center', white, [], [], [], [], [], rect);
end
The problem is that the names of the dictionary are not shown in randomized order, and every try I had until now has thrown errors.
The main problem is that I don't know how to correctly randomize/index
the dictionary-names.
Thanks for any ideas!
To reorder the elements of a cell array, you should reference elements using ():
nameCues1 = {'Lisa','Anna', 'Sarah', 'Nina', 'resized_1.jpg' };
rIdx = randperm(numel(nameCues1));
mixedCues = nameCues1(rIdx)
which yields for the case of rIdx = [3 5 1 4 2]:
mixedCues =
1×5 cell array
{'Sarah'} {'resized_1.jpg'} {'Lisa'} {'Nina'} {'Anna'}
Then use mixedCues instead of nameCues1.
See also: Access Data in Cell Array.
I am having a problem getting the default WinForms Chart control to work. I have a single chart with a single area. In this area, I want to display three (3) series whose labels are on a single legend.
Each of the value arrays shown in the code below contains six (6) values.
When I run the application the chart is only showing the background with the title and the name of the FIRST series I defined, the others seem to be ignored. Also, no grid and no data points or lines are displayed. The chart is basically blank.
this.chart.SuspendLayout();
this.chart.ChartAreas.Clear();
this.chart.Series.Clear();
ChartType chartType = ChartType.Column;
// prepare the area
const string AREA_NAME = "ChartAreaBP";
ChartArea bpChartArea = new ChartArea(AREA_NAME);
bpChartArea.AxisX.LabelStyle.Format = "dd/MMM\nyyyy";
bpChartArea.AxisX.MajorGrid.LineColor = System.Drawing.Color.LightGray;
bpChartArea.AxisY.MajorGrid.LineColor = System.Drawing.Color.LightGray;
bpChartArea.BackColor = System.Drawing.Color.LimeGreen;
bpChartArea.BackGradientStyle = GradientStyle.DiagonalRight;
bpChartArea.Position.Auto = true;
bpChartArea.InnerPlotPosition.Auto = true;
this.chart.ChartAreas.Add(bpChartArea);
// prepare the values. X is Date/time all other 3 are BYTE/INT
var xvals = from x in items select x.TimeStamp;
var yvalsSys = from y in items select y.Systolic;
var yvalsDia = from y in items select y.Diastolic;
var yvalsRhy = from y in items select y.Rhythm;
// The first series, other 2 omitted from HERE for simplicity
const string SYS_SERIES = "Systolic";
Series sysBPSeries = new Series(SYS_SERIES, 4);
sysBPSeries.ChartType = chartType;
sysBPSeries.ChartArea = AREA_NAME;
sysBPSeries.XValueType = ChartValueType.Auto;
sysBPSeries.YValueType = ChartValueType.Date;
sysBPSeries.XAxisType = AxisType.Primary;
sysBPSeries.YAxisType = AxisType.Primary;
sysBPSeries.Enabled = true;
this.chart.Series.Add(sysBPSeries);
this.chart.Series[SYS_SERIES].Points.DataBindXY(xvals, yvalsSys);
// here the other two series are defined.
But when I run the application only the legend of the FIRST series is shown even though the other two are defined in the code (I omitted them from this listing) just the same way as the first series.
And as I stated above, no grid nor values are shown. However, the chart shown in design mode does show all three labels on the first and only legend and all three lines.
I have currently made a game featuring one player. I also made a character screen where the user can choose which character he/she wants to play with. How do I make it so that a certain high score unlocks a certain character, and allows the user to equip this character to use in the game?
Right now my player has his own swift file that defines all the properties of him:
import SpriteKit
class Player: SKSpriteNode, GameSprite {
var initialSize = CGSize(width:150, height: 90)
var textureAtlas: SKTextureAtlas = SKTextureAtlas(named: "Rupert")
let maxFlyingForce: CGFloat = 80000
let maxHeight: CGFloat = 900
var health:Int = 1
var invulnerable = false
var damaged = false
var damageAnimation = SKAction()
var dieAnimation = SKAction()
var forwardVelocity: CGFloat = 190
var powerAnimation = SKAction()
init() {
super.init(texture:nil, color: .clear, size: initialSize)
createAnimations()
self.run(soarAnimation, withKey: "soarAnimation")
let bodyTexture = textureAtlas.textureNamed("pug3")
self.physicsBody = SKPhysicsBody(texture: bodyTexture, size: self.size)
self.physicsBody?.linearDamping = 0.9
self.physicsBody?.mass = 10
self.physicsBody?.allowsRotation = false
self.physicsBody?.categoryBitMask = PhysicsCategory.rupert.rawValue
self.physicsBody?.contactTestBitMask = PhysicsCategory.enemy.rawValue | PhysicsCategory.treat.rawValue | PhysicsCategory.winky.rawValue | PhysicsCategory.ground.rawValue
func createAnimations() {
let rotateUpAction = SKAction.rotate(toAngle: 0.75, duration: 0.475)
rotateUpAction.timingMode = .easeOut
let rotateDownAction = SKAction.rotate(toAngle: 0, duration: 0.475)
rotateDownAction.timingMode = .easeIn
let flyFrames: [SKTexture] = [
textureAtlas.textureNamed("pug1"),
textureAtlas.textureNamed("pug2"),
textureAtlas.textureNamed("pug3"),
textureAtlas.textureNamed("pug4"),
textureAtlas.textureNamed("pug3"),
textureAtlas.textureNamed("pug2")
]
let flyAction = SKAction.animate(with:flyFrames, timePerFrame: 0.07)
flyAnimation = SKAction.group([SKAction.repeatForever(flyAction), rotateUpAction])
let soarFrames:[SKTexture] = [textureAtlas.textureNamed("pug5")]
let soarAction = SKAction.animate(with: soarFrames, timePerFrame: 1)
soarAnimation = SKAction.group([SKAction.repeatForever(soarAction), rotateDownAction])
This is not all the code but you get the point.
I then say: let player = Player() in my Gamescene file which essentially attaches all the attributes in the player file to my player that will be seen in the Gamescene. Even if I am able to replace the initial player with a certain different player, there are so many animations that I don't know how to replace everything at once. I want to set a condition that spans over both the gamescene class and the player class so that it can just sub out certain images for other ones and keep the same actions.
Thank you for any help!
Here are some techniques you can use for making things like this more manageable:
Have a naming convention for your character images and/or sprite sheets, so that you can pass in a name to your Player() constructor. Then, instead of loading texturenamed("pug3"), you load up texturenamed("\(playerName)3"). If the only difference between your characters are the sprite sheets, this is actually all you need on the Player end.
If your characters are more complex, with differences beyond just the images, like being larger or having more health, then you will probably want to go with a more data-oriented approach. There are a couple of approaches to this, but a handy one is to read your texture names, hitbox sizes, health levels, etc., out of a .plist file instead of hard-coding them. Then just pass in the name of the .plist file to load for the character you want. Then, to create a new character, you just create a new .plist file. Another approach would be to create a "character definition" struct that you could pass to the Player constructor that contains the information you need to construct the player (this, in turn, could be loaded from a .plist file, as well, but you could also hard-code them or save them directly using codable serialization).
If neither of the above approaches are sufficient, say if you need different behavior between characters, you could always go the subclassing route - pull the various parts and pieces out into functions, and then override those functions to add the specific functionality you need for more complex characters.
I am currently working on digitizing a card game a friend and myself designed, however I am having trouble with some of the coding in regards to the basics of it. What I have so far is the code will populate a "deck" (array) then randomize it then deal 4 four cards into a "hand" (array) it then currently loads movieclips of the 4 array entries onto the stage at certain co-ordinates.
What I want to do instead since I will quickly run out of room on stage is have set defined locations for each card type (currently they just load in what ever order they were drawn)
What I'm struggling with is getting the code to 1) perform a check if the array contains at least one of any card then load said card on the stage in it's co-ordinates then populate a dynamic text box to show how many of that card are in the hand.
So I'm pretty confident with most of the simpler functions but not creating an If statement to check for certain cards (objects) in an array, and also how to count how many duplicate objects of a certain type are in the same array.
Here is what I have currently, thanks in advance.
import flash.display.MovieClip;
stop();
//Create starting deck for player 1
var deck1 : Array = new Array(new attack(),new attack(),new attack(),new attack(),new attack(),new attack(),new ashe1(),new ashe1(),new flashss(),new ignitess());
//Create empty hand for player 1 and set up display variables
var hand1 : Array = [];
var attack1
var sa1
var sa2
var sa3
var sau
var ss1
var ss2
//Check player 1's deck
trace(deck1);
//Shuffle player 1's deck
function randomize1 (a : *, b : * ) : int {
return ( Math.random() >.5 ) ? 1 : -1;
}
trace(deck1.sort( randomize1 ) );
//Draw first four cards for player 1
var drawcard1:MovieClip = deck1.shift();
trace(deck1);
trace(drawcard1);
hand1.push(drawcard1);
trace(hand1);
drawcard1 = deck1.shift();
trace(deck1);
trace(drawcard1);
hand1.push(drawcard1);
trace(hand1);
drawcard1 = deck1.shift();
trace(deck1);
trace(drawcard1);
hand1.push(drawcard1);
trace(hand1);
drawcard1 = deck1.shift();
trace(deck1);
trace(drawcard1);
hand1.push(drawcard1);
trace(hand1);
//Show player 1's hand on screen
addChild(hand1[0]);
hand1[0].x = 0.00;
hand1[0].y = 600.00;
addChild(hand1[1]);
hand1[1].x = 186.85;
hand1[1].y = 600.00;
addChild(hand1[2]);
hand1[2].x = 373.70;
hand1[2].y = 600.00;
addChild(hand1[3]);
hand1[3].x = 560.55;
hand1[3].y = 600.00;
//Show remaining card count left in deck on screen
var deck1l = deck1.length ;
player1count.text = deck1l
Make a class cor the cards, then make subclasses for each type of card.
ie, you'll have class Card which will hold all the common properties of the cards. Then you might have CombatCard, ActionCard, PassiveCard, etc.
When drafting, you could use a simple and effective method to position them in the stage. Something like this:
Each card will have a public property type, which will be an int. ie, CombatCard's type will be 2.
Then you will have a vector of Points with the positions for each type of card, where each position corresponds to each card type. So the third element in the vector would have the coordinates to place combat cards.
When drafting, you would simply call a positionCard(card) which will read its type and add it to the point where it belongs.
I'm learning Corona SDK and I'm making small project in that purpose.
So, my problem is next one:
I managed to create 2 physics objects and make one of them "explode" when it collides with the other one. My question is how to make other object (it has linear impulse applied) stop when it collides? Also, when it stops, it has to be removed from the screen to avoid colliding with other objects...
Here is a part with removing first object on collision:
nloDrop = function()
local nlo = display.newImageRect("nlo.png", 65, 25)
nlo.x = 35 + mRand(410) ; nlo.y = -60
physics.addBody(nlo, "dynamic", {density=1, bounce = 0, friction = 0, filter = {maskBits = 4, categoryBits = 2}})
nlo:applyLinearImpulse(0, 0.8, nlo.x, nlo.y)
nlo.isSensor = true
nlo.collision = nloCollision
nlo:addEventListener("collision", nlo)
nlo.name = "nlo"
toFront()
end
And here is 'collision' function:
function nloCollision(self, event)
if ((event.other.myName == "weaponName") then
print("funkc")
self:removeSelf()
self:removeEventListener("collision", nlo)
self = nil
if weapon ~= nil then
-- stop moving of weapon
end
end
end
Thanks!
You can make the object bodyActive false and then it will not respond to physics. You cant remove a body from physics within the active screen so its a better option to keep that object out of the screen.
I made it setting the object like local variable and making a function that deletes/removes each variable (object) after some interaction or collision.
1st function contains object creating (that is a local type under function) and applying physics to that object.
2nd function contains deleting (self:removeSelf()) that works because each object is object for itself and when deleting it, physics stuff will continue to work because new local object is going to be created.
function create(event)
local weap1 = display.newImage("weap1.png", 0, 0)
weap1.x = turret.x ; weap1.y = turret.y
weap1.rotation = turret.rotation
weap1.collision = weap1Collision
weap1:addEventListener("collision", weap1)
physics.addBody(weap1, "dynamic", {density = 1, friction = 0, bounce = 0, filter = {maskBits = 2, categoryBits = 4}})
weap1:applyLinearImpulse(forceWeap1*xComp, forceWeap1*yComp, weap1.x, weap1.y)
function weap1Collision(self,event)
if (event.other.name == "collisionObject") then
self:removeSelf()
self:removeEventListener("collision", weap1)
self = nil
end
end
local type of variable (object) makes it work.
P.S.: vanshika, thanks for your answer, it's useful ;)